PWA (progressive web application) is the technology that many big websites are endorsing, is supported by all the major browsers (although not yet available everywhere) and Google is pushing for it really aggressively. This is something that Joomla 4 should really take into consideration.
So is this RFC about PWAs? Not exactly but the idea here is to help the PWA implementation be the best possible out there.
Ok, so what's this idea about?
As the title denotes it's about splitting css and scripts to critical and non critical.
Why?
Both CSS and SCRIPT tags are render blocking elements, meaning if you pass a 200kb css then the page needs to load that css completely, parse it and apply it before continuing reading the rest of the html content. In plain english you get a blank screen till those elements are fetched, parsed and executed. This is hugely bad UX especially for mobile users where the mean loading time is around 15seconds.
(possible) Solution:
Split the assets to critical/non critical. All critical css/scripts gets inserted as inline styles or scripts and the rest are lazy loaded inside a noscript
tag!
Caveats:
Basically the one caveat here is that Joomla is using Bootstrap and that css framework, although version 4 is supposed to be the latest and greatest, is based on a previous era: it's monolithic. In order to have this kind of splitting we need a more flexible base, where we can specify what is critical and what not. Bootstrap is a take it all as is. Javascript is in a better position (unless someone puts a script on the critical path with a dependency on jQuery
Load times for Time To First Content Paint reduced radically, we smooth the road for PWAs
Idea straight from the Google chrome devs and esp from this repo: https://github.com/GoogleChromeLabs/ProgressiveWordPress
Labels |
Added:
?
|
To be overly blunt, this seems like more pandering to tools like PageSpeed Insights. Yes, it's a real concern, but I don't think there is a user friendly solution for a CMS.
At the CMS level, there is not an efficient way to declare CSS lines critical or non critical to decide what must be rendered inline. The reality of it is if your markup is structured correctly none of it is essential, but then you start doing crazy things like loading CSS at the end of the body and giving a flash of unstyled content on every page load (yes I've actually seen people do this one BTW).
can we use something like this https://github.com/addyosmani/critical
No. At first glance it would mean every site has to be compiled with a Node based tool and the tooling has to be able to parse rendered HTML. We don't have fully rendered HTML documents in the filesystem.
@brianteeman that will require a node/npm/gulp installation, so I guess is not a good fir for joomla. Unless joomla requires hosting with node/npm/gulp support...
At the CMS level, there is not an efficient way to declare CSS lines critical or non critical to decide what must be rendered inline.
So, Joomla, by design, is modularised, meaning that components, modules, plugins are modules
. If every module
already registers it's own css/script the required action shouldn't be something more than introducing a addCriticalStyleDeclaration
next to the existing addStyleDeclaration
. So the existing function will result to non critical and if the dev needs to pumper their code to render fast they should register some critical css. Nothing breaks and this is progressive. If someone ignores the critical the site will still load normally!
The whole idea here is about changing the current status quo from monolithic css to modular critical/non critical css, without majorly disrupting the devs.
Category | ⇒ | Feature Request |
Status | New | ⇒ | Discussion |
At first glance I like the idea. If I understand this correctly, only the template CSS could be loaded in the head (critical). In reality by removing bootstrap from the template, the CSS for the template should be relatively small. The current template should definitely clock in at less than 50kb. Component CSS (inc. bootstrap if required) would then be loaded in the noscript (non critical). The idea is still fresh in my head but I certainly see some potential in what @dgt41 is suggesting here.
An API change is needed for what then? addStyleSheetDeclaration() already renders CSS inline in the head, if you want it to include a file's contents then instead of passing a raw string pass the result of file_get_contents().
Ultimately for what you want to do to work it requires devs to change how their extensions are built or someone like you to override all the things to change the output to your preference. Either way I don't see what needs to change other than getting into the philosophical debate over what is critical CSS for each of the core elements.
An API change is needed for what then?
The difference between critical and non critical is that the later will be rendered inside a <noscript>
and will be laysyloaded on DOMContentLoaded
event (through core.js). Obviously you can't (or you may depending on your skills, project) determine which one should go where in the template without any hint.
Either way I don't see what needs to change other than getting into the philosophical debate over what is critical CSS for each of the core elements.
Maybe I have an over simplified view of this but generally speaking only the template CSS would be considered critical as this negotiates the broader layout and styling etc? Components/modules decide if bootstrap or extra CSS is loaded and if it is considered critical or not?
The difference between critical and non critical is that the later will be rendered inside a and will be laysyloaded on DOMContentLoaded event (through core.js). Obviously you can't (or you may depending on your skills, project) determine which one should go where in the template without any hint.
I think we're talking about two different things here.
addStyleSheetDeclaration()
is the inline CSS method, that wouldn't have to change as far as API or where it's rendered by the default head rendereraddStyleSheet()
is the <link>
producing CSS method, to do what you suggest would introduce a rather hard B/C break in the head rendering and a non-breakable dependency to the core JavaScript API (this may be OK for our core templates, but this dependency must be avoidable in the ecosystem if so desired)I meant addStyleSheet()
not the inline method
would introduce a rather hard B/C break in the head rendering and a non-breakable dependency to the core JavaScript API
The second part is correct, we're adding a dependency to core.js. About the first part: I don't see the B/C break here. The styles will be loaded even if js is disabled. The only difference (visually) will be that the content might be presented unstyled till the css files are fetched, parsed, applied. But I don't see that as a B/C break, in current codebase you get blank screen till css is parsed, with this proposal you get the content immediately but unstyled (if nothing is pushed in the critical part).
It's a major change in the markup and dependency chain, and one that's not easily changed if you don't want this particular behavior.
I'm not 100% against the idea to be clear. But (and this may be ignorance on my part more than anything) there is still a part of me that feels like these types of optimizations are more for appeasing tools than having practical benefits, especially if you can build your resource tree correctly (you've seen some of the work I've put into the Framework site; granted it's not a CMS install but with the size and number of resources it requires it surely doesn't need this methodology applied to it).
IMO we need to keep things so that someone can turn off this behavior if desired and avoid a mandatory dependency or dictated style of loading things. Ultimately this should be template decisions in full, but we're still dealing with a less-than-optimal part of the PHP API (the Document class itself for registering assets and the renderers for building the markup) so we do have to handle things carefully.
I fully agree with the concept, however, Joomla 4 supports rel="preload"
(I believe it got merged anyway) which isn't yet supported in FF but will be at some point. IE doesn't support it but I don't care.
So to prevent render blocking CSS, simply use this attribute and value which will set the loading of the file to as low priority as possible.
Other CSS can be pushed to before the closing body tag.
I do this with my own site at template level, which I believe it should be, as opposed to CMS level
Status | Discussion | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2017-10-30 21:49:52 |
Closed_By | ⇒ | dgt41 |
Status | Closed | ⇒ | New |
Closed_Date | 2017-10-30 21:49:52 | ⇒ | |
Closed_By | dgt41 | ⇒ |
@mbabker so rel="preload"
is not really helpful for either the css or the js as both are block-rendering assets, but it can be used with fonts eg <link rel="preload" href="/fonts/ElenaWebRegular/ElenaWebRegular.woff2" as="font" type="font/woff2" crossorigin>
. The idea behind the critical path is to drastically decrease the time to first paint, and for this case the preload is not a solution
Status | New | ⇒ | Discussion |
Labels |
Added:
J4 Issue
?
|
Status | Discussion | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2018-08-29 10:21:07 |
Closed_By | ⇒ | dgrammatiko |
can we use something like this https://github.com/addyosmani/critical
had it bookmarked for a while but not looked deeply at it