5 ms·
The problem i've always had with this, and the "above the fold" rule as it appears in the pagespeed insights tool, is the definition of "fold" varies wildly. S
by andrewingram 11y ago
The problem i've always had with this, and the "above the fold" rule as it appears in the pagespeed insights tool, is the definition of "fold" varies wildly.
So I see CSS optimisation as a multi-step process.
* Switch to a component-based rendering architecture (I favour React)
* Map CSS rules directly to components (I use CSS Modules)
* Have a JavaScript entry-point per route. The entry-point should only contain what's needed for that route, common bundles can be used too (I use webpack for this).
* Have equivalent CSS entry points per route (again, Webpack).
* On initial (ie server) render, render a style tag into the document that contains the content of the relevant entry CSS. By definition this is very close to being only the CSS required for that page (if your components have various different classes depending on config, there may be some bloat here, not sure if there's a workaround).
* On that same render, don't include an external reference to the actual stylesheets. (At this point we're mimicking Google's advice)
* On first client-side navigation (yeah, i'm assuming you're using client-side routing), load the required stylesheets for the destination URL, remove the style tag, then continue the navigation.
I'm actually excited, because in the React ecosystem, we're not too far removed from this entire process being relatively trivial to implement. I'm assuming other ecosystems are similar.
- danjordan 11y agoDoes this have any negative effects on browser caching?
- andrewingram 11y agoThe only part of the process that's a bit weird is loading style sheets programmatically. But I think people normally do that by adding a link tag to the DOM, so it should use browser caching as usual. The other caveat is that the nature of generating common bundles automatically means that what's in those bundles will vary whenever the code is changed. This means that you'll lose the benefits of browser caching each time you release. If you have dependencies that you can guarantee will be in the common bundle (like it's safe to say React will always be in it, along with any other architectural libraries), then you're better off externalising them to somewhere that sticks around between releases (and therefore benefits more from browser caching). This will also make your common bundles much smaller.
- acjohnson55 11y agoYes, bundling can potentially negatively impact caching. In the worst case, the bundles are mostly the same. Also, if your leaf component style files change rapidly, you'll invalidate the hashes on large bundles pretty frequently. For this reason, I think a better solution might be to inject critical styles into a STYLE tag in the HEAD, and then deliver one style file per component. The intuition behind this is that you can do your initial render with only the original payload (ideally in the first roundtrip), and that will buy you plenty of time for the cascade of web requests to get all the individual component files. With HTTP/2 multiplexing coming, there's no much penalty there. And then you get to cache your page at the granularity of a single component.
- oneeyedpigeon 11y agoI fear that we're on the verge of an era of 'fold-sniffing'. Actually, there are plenty of examples of annoying 'lazy-loading' scripts that defer image loading until images are visible, which just result in loads of stuttering page scrolls, waiting for images to appear. If I'd wanted an annoying interuption-filled streaming experience, I'd be watching netflix, not browsing your website...