推迟非关键 CSS

Demián Renzulli
Demián Renzulli

CSS 文件是会阻塞渲染的资源:必须先加载和处理这些文件,然后浏览器才能渲染网页。包含不必要的大型样式表的网页需要更长时间才能呈现。

在本指南中,您将学习如何推迟非关键 CSS,以优化关键渲染路径并改进首次有意义的绘制 (FCP)

示例:CSS 加载方式不理想

以下示例包含一个包含三个隐藏文本段落的折叠式列表,每个段落都采用不同的类设置样式:

此页面请求包含 8 个类的 CSS 文件,但并非所有这些类都必须用于呈现“可见”内容。

本指南的目标是优化此网页,使其仅同步加载关键样式,而其余样式(包括段落样式)以非阻塞方式加载。

测量

页面上运行 Lighthouse,然后前往性能部分。

该报告显示 First Contentful Paint 指标的值为“1 秒”,以及消除阻塞渲染的资源这一优化建议,该建议指向 style.css 文件:

未优化的网页的 Lighthouse 报告,其中显示了 FCP 为“1 秒”,并且在“机会”下方显示了“消除阻塞资源”
Lighthouse 报告建议您简化样式表,以加快网页加载速度。

如需直观了解此 CSS 如何阻止渲染,请执行以下操作:

  1. 在 Chrome 中打开相应网页
  2. Control+Shift+J(在 Mac 上,按 Command+Option+J)打开 DevTools。
  3. 点击效果标签页。
  4. 在“效果”面板中,点击重新加载

在生成的轨迹中,您会看到 FCP 标记会在 CSS 加载完毕后立即放置:

未优化页面的 DevTools 性能轨迹,显示了 FCP 在 CSS 加载后开始。
在未优化的演示页面上,CSS 加载完毕之前不会发生 FCP。

这意味着,浏览器需要等待所有 CSS 加载并处理完毕,然后才能在屏幕上绘制单个像素。

优化

如需优化此页面,您需要知道哪些类被视为关键。如需确定这一点,请使用覆盖率工具

  1. 在 DevTools 中,按 Control+Shift+PCommand+Shift+P (Mac) 打开命令菜单
  2. 输入“覆盖率”,然后选择显示覆盖率
  3. 点击重新加载以重新加载网页并开始捕获覆盖率。
CSS 文件的覆盖率,显示未使用的字节占 55.9%。
覆盖率报告会显示在初始网页加载期间实际使用的 CSS 代码量。

双击报告即可查看详细信息:

  • 标记为绿色的类至关重要。浏览器需要这些元素来呈现可见内容,包括标题、副标题和手风琴按钮。
  • 标记为红色的类是非关键类,只会影响无法立即看到的内容,例如隐藏的段落。

有了这些信息,您就可以优化 CSS,以便浏览器在网页加载后立即开始处理关键样式,并将非关键 CSS 延迟到稍后处理:

  1. 提取覆盖率报告中标记为绿色的类定义,并将这些类放在页面开头的 <style> 代码块中:

    <style type="text/css">
    .accordion-btn {background-color: #ADD8E6;color: #444;cursor: pointer;padding: 18px;width: 100%;border: none;text-align: left;outline: none;font-size: 15px;transition: 0.4s;}.container {padding: 0 18px;display: none;background-color: white;overflow: hidden;}h1 {word-spacing: 5px;color: blue;font-weight: bold;text-align: center;}
    </style>
    
  2. 通过应用以下模式,异步加载其余类:

    <link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
    <noscript><link rel="stylesheet" href="styles.css"></noscript>
    

这不是加载 CSS 的标准方式。具体方法如下:

  • link rel="preload" as="style" 异步请求样式表。如需详细了解 preload,请参阅“预加载关键素材资源”指南
  • link 中的 onload 属性可让浏览器在样式表加载完毕后处理 CSS。
  • 在使用 onload 处理程序后将其“置 null”有助于某些浏览器在切换 rel 属性时避免重新调用该处理程序。
  • noscript 元素中对样式表的引用为不执行 JavaScript 的浏览器提供了回退选项。

生成的页面与之前的版本完全一样,即使大多数样式以异步方式加载也是如此。下面是 HTML 文件中内嵌样式和对 CSS 文件的异步请求的外观:

监控

使用 DevTools 对经过优化的页面运行另一个性能轨迹。

FCP 标记会在网页请求 CSS 之前显示,这意味着浏览器无需等待 CSS 加载即可渲染网页:

优化后的网页的开发者工具性能轨迹,显示了 FCP 在 CSS 加载之前开始。
在经过优化的页面上,FCP 可以在样式表格加载之前开始。

最后一步,在经过优化的网页上运行 Lighthouse。

在报告中,您会看到 FCP 页面缩短了 0.2 秒(改进了 20%):

Lighthouse 报告,其中显示 FCP 值为“0.8 秒”。
缩短的 FCP 时间。

移除阻塞渲染的资源建议不再显示在优化建议下,而是显示在已通过审核部分:

Lighthouse 报告的示意图,其中“通过的审核”部分显示了“消除屏蔽资源”。
该网页现已通过阻塞资源审核。

后续步骤和参考文档

在本指南中,您学习了如何通过手动提取页面中的未使用代码来推迟非关键 CSS。对于更复杂的生产环境,提取重要 CSS 指南介绍了一些最常用的提取重要 CSS 的工具,并包含一个 Codelab,以便了解这些工具在实践中的运作方式