Generate critical CSS for your website with node

Artikel aktualisiert am: von Jens Martsch
Generate critical CSS for your website with node

You just finished your website. You upload it and test it in Google Lighthouse and get an error saying "Eliminate render-blocking resources" and a bad performance score.

So "How do I eliminate render-blocking resources?" you ask yourself. Well, I provide you with a solution.

What are render-blocking resources?

Render blocking resources are static files, such as fonts, HTML, CSS, and JavaScript files, that are vital to the process of rendering a web page.

When a render blocking resource is encountered, the browser stops downloading the rest of the resources until these critical files are processed. Until then the rendering process is blocked.

What is critical CSS?

It is a minimum set of blocking CSS, or the critical CSS, that we need to make the page appear to the user.

You can learn more about critical CSS here: https://web.dev/extract-critical-css/ or here https://www.smashingmagazine.com/2015/08/understanding-critical-css/

How do you generate critical CSS?

First install the needed node modules via npm install critical fancy-log log-symbols

then create a file named criticalcss.mjs (the extension stands for module js) in the root of your site folder and add the following contents to it:

npm install critical fancy-log log-symbols

then create a file named criticalcss.mjs (the extension stands for module js) in the root of your site folder and add the following contents to it:

import critical from 'critical';
import log from 'fancy-log';
import logSymbols from 'log

let criticalCssConfig = {
  concurrency: 5, //this is the number of tasks that run concurrently, large numbers could lead to errors / memory leaks
  baseUrl: 'http://yoururl.localhost',
  suffix: '_critical.min.css',
  criticalWidth: 1920,
  criticalHeight: 1440,
  criticalIgnore: [
    '@font-face'
  ],
  pages: [
    {
      url: '/',
      template: 'home' // the final file name will be nameoftemplate+suffix, for example home_critical.min.css
    },
    {
      url: '/about-us/',
      template: 'page'
    },
  ]
};

criticalCssConfig.pages.forEach(page => {
  const url = criticalCssConfig.baseUrl + page.url + '?criticalcss=false';
  log(logSymbols.info, `Generating critical CSS for template ${page.template} with URL ${url}`);
  // critical.generate returns a Promise.
  critical.generate({
    // Inline the generated critical-path CSS
    // - true generates HTML
    // - false generates CSS
    inline: false,

    // Your base directory
    base: './',

    // HTML source

    // HTML source file
    src: url,

    // Your CSS Files (optional)
    // css: ['dist/styles/main.css'],

    // Viewport width
    width: criticalCssConfig.criticalWidth,

    // Viewport height
    height: criticalCssConfig.criticalHeight,

    // Output results to file
    target: {
      css: "./public/css/" + page.template + criticalCssConfig.suffix,

      // html: 'index-critical.html',
      // uncritical: 'uncritical.css',
    },

    // Minify critical-path CSS when inlining
    minify: true,

    // Extract inlined styles from referenced stylesheets
    // extract: true,

    // ignore CSS rules
    ignore: {
      atrule: ['@font-face'],
      // rule: [/some-regexp/],
      // decl: (node, value) => /big-image\.png/.test(value),
    },
  });
});

Adapt the settings in this file to your setup. For example the baseUrl, the pages array, the target.css path, where the resulting file should be saved.

Add the following line to the scripts section of your package.jsonfile:

"criticalcss": "node criticalcss.mjs",

Now when you run npm run critical the script iterates through the different URL's you provided in the pages array of the criticalCssConfig and generates a file including the critical CSS for the URL and saves it as nameofthetemplate.critical_min.css in the folder you provided under target.css.

In the following weeks we will publish more tutorials, for example "How to inline critital CSS in your Statamic 3 website.

If you are missing something please write us.