laitimes

How to use Critical CSS for front-end performance optimization?

author:Advanced front-end advanced

大家好,很高兴又见面了,我是"高级前端‬进阶‬",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。

How to use Critical CSS for front-end performance optimization?

1. Why started talking about critical path CSS

Critical path CSS is important

CSS is required to build a page's render tree, and JavaScript often blocks CSS during the initial build of a page. Therefore, developers should ensure that any non-essential CSS is marked as non-critical (e.g., print and other media queries) and that critical CSS is small enough to take as short a load time as possible.

How to use Critical CSS for front-end performance optimization?

With the help of key CSS, users can get the basic style as quickly as possible, and because it's <head>right in the element in the document<style>, there are no additional requests to the server to get the stylesheet > wait for the requested style to load and render.

How to use Critical CSS for front-end performance optimization?

Then load the folded or non-critical styles below in the background to avoid rendering blocking.

Critical path CSS should be inline

For best performance, developers may want to consider inlining key CSS directly into HTML documents.

How to use Critical CSS for front-end performance optimization?

Inline CSS eliminates extra round trips in the critical path and, if set correctly, can be used to provide a "single round trip" critical path length where only HTML is a blocking resource.

2.critical.js Basic Usage

critical.js is used to extract key content from HTML and inline critical path CSS, such as above the fold. critical.js is open source on Github, has more than 10k stars, and is very simple to use at the same time:

import { generate } from 'critical';           

The following configuration options are also supported:

generate({
  // Inline the generated critical-path CSS
  // - true generates HTML
  // - false generates CSS
  inline: true,
  // Your base directory
  base: 'dist/',
  // HTML source
  html: '<html>...</html>',
  // HTML source file
  src: 'index.html',
  // Your CSS Files (optional)
  css: ['dist/styles/main.css'],
  // Viewport width
  width: 1300,
  // Viewport height
  height: 900,
  // Output results to file
  target: {
    css: 'critical.css',
    html: 'index-critical.html',
    uncritical: 'uncritical.css',
  },
  // 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),
  },
});           

The following example is used to generate critical path CSS and is a basic usage example:

generate({
  base: 'test/',
  src: 'index.html',
  target: 'styles/main.css',
  width: 1300,
  height: 900,
});           

The following example generates and compresses critical path CSS:

generate({
  base: 'test/',
  src: 'index.html',
  target: 'styles/styles.min.css',
  width: 1300,
  height: 900,
});
           

The following example is used to generate, compress, and inline critical path CSS:

generate({
  inline: true,
  base: 'test/',
  src: 'index.html',
  target: {
    html: 'index-critical.html',
    css: 'critical.css',
  },
  width: 1300,
  height: 900,
});           

It is worth mentioning that the generate method supports callback and promise to return the processed result, for example, the following is the way of promise:

generate({
    base: 'test/',
    src: 'index.html',
    width: 1300,
    height: 900
}).then((({css, html, uncritical})) => {
    // You now have critical-path CSS as well as the modified HTML.
    // Works with and without target specified.
    ...
}).error(err => {
    ...
});           

3.critical.js Advanced usage

Generate critical path CSS with multiple resolutions

This is a useful option when the website is responsive and the developer wants to provide key CSS for multiple screen resolutions. It's worth noting, however, that the final output will be compressed to eliminate duplicate rule inclusions.

generate({
  base: 'test/',
  src: 'index.html',
  target: {
    css: 'styles/main.css',
  },
  dimensions: [
    {
      height: 200,
      width: 500,
    },
    {
      height: 900,
      width: 1200,
    },
  ],
});           

Generate critical path CSS and ignore specific selectors

When a developer wants to defer loading a web font or background image, they can do so in the following ways:

generate({
  base: 'test/',
  src: 'index.html',
  target: {
    css: 'styles/main.css',
  },
  ignore: {
    atrule: ['@font-face'],
    decl: (node, value) => /url\(/.test(value),
  },
});
           

For more advanced usage, please refer to the material at the end of this article, which will not be expanded into too much in this article.

A viable alternative to 4.critical.js

It's worth mentioning Penthouse, and FilamentGroup also maintains a key CSS node module, similar to Penthouse, which finds and outputs the page's critical path CSS.

When developers enable Priority_ritic_css filters, the PageSpeed Optimization module for nginx, apache, IIS, ATS, and Open Lightspeed automates all the heavy lifting.

This article focuses on Penthouse, and other similar modules can be found in the reference at the end of this article. The main differences between Critical and Penthouse include the following:

  • Critical automatically extracts the stylesheet from the HTML and generates critical path CSS, which other modules often require the developer to specify beforehand.
  • Critical provides a way to inline critical path CSS (a common next step logic after generating CSS)
  • Being able to pull out some ugly boilerplate files that would otherwise need to be addressed separately because of the fact that both generation and inline are handled

In summary, if your website or application has a large number of styles that need to be dynamically injected into the DOM, which is sometimes common in Angular applications, it is recommended to use Penthouse directly. However, Penthouse requires developers to provide styles upfront, which may in some cases provide more accuracy than Critical.

Resources

https://github.com/addyosmani/critical

https://github.com/addyosmani/critical-path-css-demo

https://github.com/filamentgroup/criticalCSS

https://github.com/pocketjoso/penthouse

https://www.tezify.com/how-to/defer_css_loading_with_loadcss/

https://web.dev/articles/extract-critical-css?hl=zh-cn