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
Improve blocking scripts #6372
Comments
Most blocking scripts are CSS files and not JS files according to my experience. |
👍 I agree that the synchronous (blocking) loading of JS in the But I see several issues with it:
The first issue could be solved by using a custom function instead of an event I think. But the second one will be hard to solve... We probably don’t want to use a module loader and require every script to be a module. |
Yeah CSS is blocking too, especially the stuff that is considered to be not critical. But the difference here is that I feel like webdesigners can handle CSS and they know where it is blocking and where it's not. They can also split files if needed, reorganize etc.
Of course, there are more issues with it. For example we would need multiple events to be fired when we combine multiple scripts into one 😄 That's why this is an RFC issue. I would like to find a solution and I'm sure there is one. If Contao cannot fix it out-of-the-box, to me that means 99% of all users won't be able to fix it either. That's why I think this is a really relevant topic. Coming back to your remarks: 1 & 2 sort of go together, I agree. Is there maybe a library that does all of that and is reasonably small? |
Something like https://github.com/muicss/loadjs could maybe help? |
I totally don't understand your approach. The scripts are loaded in header because we do have inline code all over the document to render modules. If that would not be the case, we could simply place everything in the footer. That's why I stopped adding javascript to templates, or better said use |
Obviously all inline code needs to be adjusted from using domready events to the new solution. Templates are not covered by the BC promise so there's no issue with that. |
So why would we need anything and an event in the header at all? Just add everything to body? |
Please elaborate on how your solution would work, please. |
You could also add |
And how do inline gallery scripts wait until this is loaded? |
well they don't. Same as with the event, they must be added after the initial scripts. Basically, do not inline. Use |
An alternative would be to introduce a real module loader, not sure how that would work with such a setup though. But we sure should not invent our own loading system… |
That doesn't work for combined scripts that's why I wanted to move all |
Why would that not work for combined scripts? Where's the difference between loading in header and footer if the order is correct? |
What about running the whole rendered html through a filter that moves all script tags to the bottom while keeping their order? I have such a solution working in Magento systems: https://github.com/bobbyshaw/magento-footer-js |
That would certainly work somehow but it's a slow and possibly unreliable solution (especially when you use regular expressions the way magento-footer-js does instead of DOM traversal) and I would like to see if there are other options first :) So that would be my last resort. But maybe still better than nothing at all, we'll see :) |
Doesn't Theme+ do this? |
There are quite a few extensions that apply stuff on the resulting HTML and I think we don't need this. |
None of them are perfect though imho. |
And it will break for everything that does document.write or similar stuff.
|
AFAIK loading the scripts in the head asynchronously is much better than loading them in the footer synchronously. Async should allow more parallelism and doesn’t block the domready event. I found an article that describes how to load scripts asynchronously and keep the desired execution order: https://www.html5rocks.com/en/tutorials/speed/script-loading/. IMO that would be the best option for our use-case. |
Is that article from 2013 still valid? BTW I liked the part where he writes:
;) Four years later "subresource" is still not supported by all browsers and so scripts may be hidden from preloaders. It's a trade-off. Well, at the moment I manually extract scripts, process them via task runner and add one resulting script as async. I include basic critical CSS to style e. g. slides before the actual slider is loaded (which is also done async). At least I can confirm that the above mentioned method to automatically move everything to the bottom is working on production sites and saves me some time as long as it's running smoothly. |
I stumble upon this
But colorbox, accordion ... are not loaded in the head? Can you explain what you mean? |
What's the status of this one? |
Maybe we should promote the use of Symfony Encore (and possibly add an option to include assets in the layout) instead of trying to improve on legacy implementations? |
@aschempp We have an bundle doing exactly this: https://github.com/heimrichhannot/contao-encore-bundle . Maybe it can act as a first approach for having a contao core-supported way? |
Looks pretty interesting! Have you considered creating a pull request to have something merged to the core? |
…123) Description ----------- Closes #618 Complementary commit: contao/tcpdf-bundle@0c377c3 Commits ------- 10c2d6d1 Do not strip forms in the ModuleArticle::generatePdf() method (see #618)
Why building an own script loader? Only thing that has to be changed this way, is inline script. an example <script>
const myCustomAccordeon = {
'foo':'bar'
}
</script>
<script src="assets/jquery.js" defer></script>
<script src="assets/contaoCustomAccordeon.js" defer></script> myCustomAccordeon.js can than just use the inline data. |
That is correct but Using |
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer true, it is delayed a little ... but in a way I usually want. I think, sticking to default HTML script Of course all this is just my opinion. |
You want that with above the fold content, e.g. click event handlers for menu buttons, and sliders. |
Hm I thought you can not register a click handler on a dom element that is not ready, yet. |
No, you can initialize it directly after or even within the element. |
Ah, good to know this. I would still prefer the default HTML defer approach. But both (above PR and defer) would be much better than the current way. |
FYI, we have discussed this again at the developer's meeting in February, 2020, and we have agreed that it does not have a high priority at the moment. Also, before we can implement the feature, we have to get rid of the MooTools and jQuery dependencies in the front end. |
I guess this is the one problem users struggle with most when analyzing page speed. Page speed insights wants us to put blocking scripts out of the way and I guess it's right about that so we should do something about it. The problem is that almost all of our scripts are loaded in
<head>
. This is especially complicated for dynamically loaded scripts (when you include a gallery, an accordion etc.) so it's very hard to fix for non-devs and I think it should work better out-of-the-box.I named this issue RFC as I request for comments here. Please do not just comment a "+1" if you think that needs to be done (you can do that by leaving feedback to the issue itself).
Please comment on concrete ideas how we could solve this.
My idea is to have a simple loader script we include in the
<head>
but inline (maybe also in<body>
at the beginning? To be discussed). Here's a first example (obviously we would minify this):For all the stuff added using
$GLOBALS['TL_JAVASCRIPT']
we then outputOur initialize scripts that mostly listen to the
domready
jquery/mootools events can then be adjusted like so:PS: My code is completely untested and just illustrates the general idea. Instead of
new CustomEvent()
we should usedocument.createEvent('CustomEvent');
for IE11 compatibility and make sure the async script is as small as possible when minified using more variables etc.The text was updated successfully, but these errors were encountered: