使用 Critical 提取和内联关键 CSS

无论您使用 UI 库还是手工制作样式,发送大量 CSS 都会延迟渲染,因为浏览器必须先下载并解析 CSS 文件才能显示页面。

这个响应式冰淇淋画廊是使用 Bootstrap 构建的。像 Bootstrap 这样的 UI 库可以加速开发,但这通常会以臃肿和不必要的 CSS 为代价,从而减慢您的加载时间。Bootstrap 4 为 187 KB,而另一个 UI 库 Semantic UI 未压缩时竟高达 730 KB。即使经过缩小和 gzip 压缩,Bootstrap 仍然重约 20 KB,远高于首次往返的 14 KB 阈值

Critical 是一种工具,可以提取、缩小和内联首屏 CSS。这样即使页面其他部分的 CSS 尚未加载,也可以尽快渲染首屏内容。在本实验手册中,您将学习如何使用 Critical 的 npm 模块。

测量

  • 要预览网站,请按 查看应用。然后按 全屏 全屏

要在此网站上运行 Lighthouse 审核,请执行以下操作

  1. 按 `Control+Shift+J`(在 Mac 上按 `Command+Option+J`)打开 DevTools。
  2. 点击 Lighthouse 选项卡。
  3. 点击 移动设备
  4. 选中 性能 复选框。
  5. 清除“审核”部分中的其余复选框。
  6. 点击 模拟快速 3G,4 倍 CPU 减速
  7. 选中 清除存储空间 复选框。选中此选项后,Lighthouse 将不会从缓存加载资源,这将模拟首次访问者体验页面的方式。
  8. 点击 运行审核

Audits panel of Chrome DevTools, powered by Lighthouse

当您在自己的机器上运行审核时,确切的结果可能会有所不同,但在影片视图中,您会注意到应用在最终渲染内容之前会有一段时间的空白屏幕。这就是 首次内容绘制 (FCP) 指标偏高的原因,也是整体性能得分不高的原因。

Lighthouse audit showing performance score of 84, FCP 3 seconds and a filmstrip view of loading the app

Lighthouse 可以帮助您解决性能问题,因此请在 机会 部分查找解决方案。消除渲染阻塞资源 被列为一项机会,而这正是 Critical 的闪光点!

Lighthouse audit 'Opportunities' section listing 'Eliminate render-blocking resources'

优化

  • 点击 Remix to Edit(混合编辑) 使项目可编辑。

为了加快速度,Critical 已安装,并且实验手册中包含一个空的配置文件。

在配置文件 critical.js 中,添加对 Critical 的引用,然后调用 critical.generate() 函数。此函数接受包含配置的对象。

const critical = require('critical');

critical.generate({
    // configuration
},(err, output) => {
  if (err) {
    console.error(err);
  } else if (output) {
    console.log('Generated critical CSS');
  }
});

错误处理不是强制性的,但它是衡量控制台中操作成功与否的简单方法。

配置 Critical

下表包含一些有用的 Critical 选项。您可以在 GitHub 上查看所有可用选项

选项 类型 说明
base 字符串 文件的基本目录。
src 字符串 HTML 源文件。
dest 字符串 输出文件的目标。如果 CSS 是内联的,则输出文件是 HTML。否则,输出是 CSS 文件。
width, height 数字 视口宽度和高度(以像素为单位)。
dimensions 数组 包含具有宽度和高度属性的对象。这些对象表示您要使用首屏 CSS 定位的视口。如果您的 CSS 中有媒体查询,则可以使用此选项生成涵盖多个视口尺寸的关键 CSS。
inline 布尔值 设置为 true 时,生成的关键 CSS 会内联到 HTML 源文件的 中。
minify 布尔值 设置为 true 时,Critical 会缩小生成的关键 CSS。为多个分辨率提取关键 CSS 时可以省略,因为 Critical 会自动缩小关键 CSS 以避免重复包含规则。

以下是提取多个分辨率的关键 CSS 的配置示例。将其添加到 critical.js 或尝试调整选项。

critical.generate({
  base: 'public/',
  src: './index.html',
  dest: './index.html',
  inline: true,
  dimensions: [
    {
      height: 500,
      width: 300,
    },
    {
      height: 720,
      width: 1280,
    },
  ]
}, (err, output) => {
  if (err) {
    console.error(err);
  } else if (output) {
    console.log('Generated critical CSS');
  }
});

在此示例中,index.html 既是源文件又是目标文件,因为 inline 选项设置为 true。Critical 首先读取 HTML 源文件,提取关键 CSS,然后使用内联在 <head> 中的关键 CSS 覆盖 index.html

dimensions 数组指定了两个视口大小:300 x 500 用于超小屏幕,1280 x 720 用于标准笔记本电脑屏幕。

minify 选项已省略,因为当指定多个视口尺寸时,Critical 会自动缩小提取的 CSS。

运行 Critical

将 Critical 添加到 package.json 中的脚本

scripts: {
  "start": "node server.js",
  "critical": "node critical.js"
}
  1. 点击 终端(注意:如果“终端”按钮未显示,您可能需要使用“全屏”选项)。

要生成关键 CSS,请在控制台中运行

npm run critical
refresh
Success message saying 'Generated critical CSS' in the console
控制台中的成功消息

现在在 index.html<head> 标记中,生成的关键 CSS 内联在 <style> 标记之间,后跟一个异步加载其余 CSS 的脚本。

index.html with inlined critical CSS
内联的关键 CSS

再次测量

按照实验手册开头的步骤再次运行 Lighthouse 性能审核。您获得的结果将类似于此

Lighthouse audit showing performance score of 100, FCP 0.9 seconds and improved filmstrip view of loading the app