critters icon indicating copy to clipboard operation
critters copied to clipboard

Improve speed of HTML processing

Open danielroe opened this issue 2 years ago • 11 comments

We've been getting reports of performance hits when using critters for per-request inlining of styles using SSR. See for example:

  • https://github.com/nuxt-community/critters-module/issues/21
  • https://github.com/nuxt/nuxt.js/issues/8569#issuecomment-873419661
  • https://github.com/vercel/next.js/pull/16539#issuecomment-877409549

What do you think? Should we be restricting critters to the initial static generation rather than running per-request?

EDIT: updated with reproduction repository: https://github.com/danielroe/critters-test

danielroe avatar Jul 13 '21 14:07 danielroe

We also seen this in Angular SSR https://github.com/angular/universal/issues/2106

alan-agius4 avatar Jul 15 '21 16:07 alan-agius4

IIRC @janicklas-ralph has done some experimenting to improve performance for this use-case. It's a trade-off though, and any caching would need to be controllable by the caller.

developit avatar Jul 15 '21 16:07 developit

@developit , @alan-agius4 , @danielroe

I successfully made a fork of Critters and implemented dropcss to prune not used CSS rules (keeping keyframes and fonts Critters features).

To parse and process stylesheets (preload strategy, merge stylesheets, etc) i'm using node-html-parser. I found it faster than parse5 to parse and serialize html. This is just a little gain of speed.

The overall result is a huge speed improvement mainly thanks to dropcss. I didn't do proper benchmarks but i would say this is around 10x faster.

The only drawback is that html and css parsers from dropcss are very sensible. Only valid html and css inputs could be processed.

I didn't push my locals commits to the forked repository yet. I will do it later and let you know if some of you are interested.

It also opens the possibility to prune external stylesheets from multiple Critters runs with the same (or not) instance. This is possible thanks to the whitelist technique from dropcss.

freddy38510 avatar Jul 16 '21 20:07 freddy38510

@freddy38510 any news on that? do you have your changes available anywhere? i'd love to try it on our project and see if it solves the performance issues

amakhrov avatar Sep 15 '21 19:09 amakhrov

@amakhrov,

I ended up creating a new project called beastcss because the code was very different from Critters.

You can make a try and open new issues if you find some bugs or for asking new features. And please, i'll be glad if you let me know about the performance improvement :)

freddy38510 avatar Sep 16 '21 00:09 freddy38510

I'm seeing 4x-5x faster processing on our typical html page after switching to dropcss-based approach. It's definitely a great boost - but still not sufficient for enabling it in production for us (with Angular Universal).

EDIT: actually, 10x using beastcss with caching of parsed stylesheets

amakhrov avatar Sep 16 '21 19:09 amakhrov

@amakhrov ,

I came to this solution under a different context than yours. I'm using a Static Site Generator for Quasar with SSR pre-rendering. Also, i didn't test beastcss with html that contains a lot of DOM nodes.

Did you measure the duration of the overall processing ? What would be the maximum acceptable duration for your use-case ?

freddy38510 avatar Sep 17 '21 12:09 freddy38510

Great question. So when we tried to enable inlineCritical on prod with Angular last time, we got around 500-600ms overhead of pure computations, and it was just too much, we started dropping requests. Frankly I'm not sure how much lower it needs to be for our case - will have to try and see, I guess. 10x improvement (with beastcss) sounds like it should do the trick.

amakhrov avatar Sep 17 '21 17:09 amakhrov

@amakhrov did beastcss do the trick? How did you go about implementing this in Angular with SSR?

brjadams avatar Dec 22 '22 19:12 brjadams

@brjadams we didn't move on with it, and just turned off inline critical CSS in the meantime

amakhrov avatar Dec 26 '22 21:12 amakhrov

I've made some changes in v0.0.19 to help with improving the speed of processing. It's a combination of adding a cache and also some user intervention. Please try this version out and let me know if it helps

janicklas-ralph avatar Jul 06 '23 18:07 janicklas-ralph