1
0 Comments

Feeling accomplished

Today, I finished a complete rewrite of critical css generation, moving it to the browser side instead of relying on css-tree module.

The reasons for reimplementing it:

  1. I needed to inline @include directives to avoid extra network lookups, which would require more hacking into addyosmani/critical
  2. addyosmani/critical fails on declarations like link rel=preload as=style href=…woff2, I mean prone to developer errors
  3. The multi-resolution critical CSS (eg I want CSS for both mobile and desktop) took too long with addyosmani/critical, around 40 seconds to generate optimized page for all the resolutions - to get a combined critical CSS I needed to re-parse CSS tree for each resolution, and run it through the whole cycle of purging/stripping, feed it into Puppeteer and then recombine multiple critical css results into a single one.
  4. New implementation allows to better detect fonts above the fold, even those referred as var(). It is still not perfect for selectors that are not directly accessible by querySelector(), eg ::after and ::before. For these I refer to :root selector for variable declarations, which is not perfect, but still better than nothing
  5. New implementation will be able to return font declarations as a separate css stylesheet, which might be useful for LCPs triggered by fonts - so I can load fonts declarations css before critical css and vice versa

Also, I’ve moved all the core tests from penthouse to the new critical generator and made sure they work as expected besides deprecated features and -moz- selectors. Also added a new test where critical CSS gets generated for multiple resolutions.

There are some drawbacks though, eg missing -moz- selectors and all the other deprecated CSS at rules (eg @viewport), but if I ever need them, I know how to address it. At the moment it seems that Firefox has already deprecated most of them, so I should be on the safe side.

on September 21, 2022