-
Notifications
You must be signed in to change notification settings - Fork 616
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[5.x]: Fix JS modules not loading correctly in the control panel #14526
Conversation
It’s important that lazy-registered JS is loaded via Maybe the PR could be adjusted to keep things the way they were, but start ignoring |
Also, we’ve been using |
Working fine in Craft 4, but you also treat scripts differently in Craft 4. Refer to _appendHtml where you just collect all the scripts and append to the You can't exclude them from |
Okay, so a more lighter touch would be: const nodes = $.parseHTML(html.trim(), true).filter((node) => {
if (node.nodeName === 'LINK' && node.href) {
if (!this._existingCss) {
this._existingCss = $('link[href]')
.toArray()
.map((n) => n.href.replace(/&/g, '&'));
}
if (this._existingCss.includes(node.href)) {
return false;
}
this._existingCss.push(node.href);
return true;
}
if (node.nodeName === 'SCRIPT' && node.src) {
if (!this._existingJs) {
this._existingJs = $('script[src]')
.toArray()
.map((n) => n.src.replace(/&/g, '&'));
}
if (!this._existingJs.includes(node.src)) {
+ this._existingJs.push(node.src);
+
+ if (node.type === 'module') {
+ return true;
+ } else {
+ scriptUrls.push(node.src);
+ }
- scriptUrls.push(node.src);
- this._existingJs.push(node.src);
}
// return false either way since we are going to load it ourselves
return false;
}
return true;
}); So that if this is detected as a module, it bypasses |
Yeah that’s what I was thinking. Can you adjust the PR and verify it works for you? |
No worries, done. |
Is it expected that the |
I'm not fully across what But we're returning a node not just the URL in that But I would expect that once loaded, a duplicate script shouldn't be loaded again - not just for script modules? |
Right.
I think so, but worth testing, e.g. by creating multiple Hyper fields in succession from the same CP page. |
So all good with the field settings, switching back and forth between types seems fine. I've also tested creating multiple fields with the new entry type + add field editor, which takes care of Matrix-like fields and sections, etc. Similarly, for entries, scripts are only loaded once for multiple Hyper fields. |
On second thought, decided to just revert to how we are loading scripts in Craft 4.5.6+, if that’s working fine. I’m a little concerned with splitting out how we load things depending on |
Fair call, I'll give that a quick test. Thanks for making sense of this PR! |
5.0.0-beta.7 is out now with that change. |
There's an issue for any field that contains a
<script type="module">
in its assets when loading its field settings. From a new field interface, selecting the field via dropdown will load the HTML/CSS/JS for the field asynchronously. This is notable with Vizy, Hyper, Icon Picker and others, where we use Vue and Vite to handle field settings.This results in an error when trying to load a script that's a module - the browser can't handle it.
This seems to stem from this change where you fetch the script first via jQuery's
$.getScript()
function, but this doesn't work well with modules. In addition, you're only passing in an array of URLs to this function, whereas we need to know if the URL is a module or not.I did toy with fetching all attributes of the
<script>
element and use that, but decided to keep it simple.So firstly, we store the script type and src, and pass into
_loadScripts()
. We then have to swap out jQuery's$.getScript()
function for our own, but I've tried to keep it almost 1-for-1.Sorry for the noisy PR, but figured I should rename some variables for clarity. I also didn't touch
this._existingJs
because it's just comparing URLs, not loading them.