How do I collect critical-css for chunks of renderToNodeStream (React SSR)

1.3k Views Asked by At

I want to implement critical-css for React SSR. There are many ways to achieve this but I'm interested particularly in this approach - I plan collect it on the fly after react renders the html. I have css on server and I want to inline only required css from it and load the rest asynchronously (I am not sure about performance but I saw production solution doing this with tools like purifyCSS, so I plan to give it a try and measure its performance)

Problem #1 - Critical CSS extraction

My SSR setup is based on renderToNodeStream not renderToString so I cant compare html with css so easily - chunk might be just a piece of invalid html without closing tags. How do I parse classnames properly in this case efficiently? RegExp might be quite slow here I guess?

Problem #2 - Inlining styles into html chunk

My plan is to get the chunk of html that comes from renderToNodeStream and inline corresponding css into response - so it will be working similarly to interleaveWithStyles method of styled-components

Here's how chunk looks after styled-components processes it - <style> node might be inserted in the middle of <svg> - I suppose its not a problem as long as I will load full css eventually, but this doesn't feel safe as this node might be easily removed e.g. by react hydrate. So what would be correct way to enrich html stream with inlined css?

enter image description here

2

There are 2 best solutions below

1
prince kumar On

create a clone of readable stream that is returned by renderToNodeStream. convert it into string and purify with css to get the critical css.

1
Anton  Korzunov On

https://github.com/theKashey/used-styles is working exactly as your desired solution:

  • scans your build folder to find all styles you can use
  • scans your HTML output collecting used styles (thus the name)
  • inlines references to used style files as well as rules in a bulk (renderToString) as well as stream(renderToNodeStream) modes
  • moves all injected code outside renderer markup just before applicating start allowing correct hydration.