优化资源加载

在上一单元中,关键渲染路径背后的某些理论是 以及阻塞渲染和阻塞解析器的资源如何导致 网页的初始渲染。现在您已经了解了 接下来,您将了解一些技巧,帮助您优化关键词 呈现路径

网页加载时,许多资源都会在网页的 HTML 中被引用, 了解其通过 CSS 呈现的外观和布局,以及其交互性 。本单元介绍与 这些资源以及它们对网页加载时间的影响

阻塞渲染

正如上一单元中所述,CSS 是一种会阻止内容呈现的资源render-blocking 因为它会阻止浏览器渲染任何内容,直到 CSS 对象模型 (CSSOM) 构建而成。浏览器会阻止呈现,以防止Flash 无样式的内容 (FOUC) - 从用户体验的角度来看是不可取的。

在上一个视频中,我们可以看到, 任何样式。随后,在网页的 CSS 文件 已从网络加载完毕,且网页的未样式版本 立即替换为自定样式的版本。

一般来说,FOUC 是指您通常不会看到的,但其概念 了解浏览器为什么会阻塞渲染 直到下载 CSS 并将其应用于网页为止。阻塞渲染 未必不可取,但您需要最大限度地缩短 保持 CSS 的优化状态。

解析器阻止

解析器阻塞资源(例如 <script>)会中断 HTML 解析器 元素。asyncdefer当解析器遇到一个 <script> 元素,则浏览器需要先评估并执行脚本,然后才能 继续解析其余 HTML。这是设计使然,因为脚本 在 DOM 仍在构建期间修改或访问 DOM。

<!-- This is a parser-blocking script: -->
<script src="/script.js"></script>

使用外部 JavaScript 文件(不包含 asyncdefer)时,解析器会 从发现文件开始,直到被下载、解析和 。使用内联 JavaScript 时,解析器同样会被阻止,直到 系统会解析并执行内嵌脚本。

<ph type="x-smartling-placeholder">

预加载扫描器

预加载扫描器是一项浏览器优化措施,采用辅助 HTML 的形式 解析器,可扫描原始 HTML 响应,以查找并推测提取 否则,主 HTML 解析器才会发现它们。对于 预加载扫描器允许浏览器开始下载 在 <img> 元素中指定的资源,即使 HTML 解析器被阻止也是如此 同时抓取和处理资源(例如 CSS 和 JavaScript)时。

若要利用预加载扫描器,应包含关键资源 。以下资源加载模式 预加载扫描器无法发现:

  • CSS 使用 background-image 属性加载的图片。这些图片 引用位于 CSS 中,预加载扫描程序无法发现这些引用。
  • 以注入 <script> 元素标记的形式动态加载的脚本 使用 JavaScript 或使用动态 import() 加载的模块插入到 DOM 中。
  • 使用 JavaScript 在客户端上呈现的 HTML。此类标记包含在 字符串,并且无法通过预加载找到 扫描程序
  • CSS @import 声明。

这些资源加载模式都是延迟发现的资源,因此 无法受益于预加载扫描程序。请尽可能避免。如果 无法避免此类模式,但您可以使用 preload 提示可避免资源发现延迟。

<ph type="x-smartling-placeholder">

CSS

CSS 决定了网页的呈现方式和布局。如前所述 是一种阻碍呈现的资源,因此优化 CSS 可能会带来 对整体网页加载时间的影响。

缩减大小

缩减 CSS 文件的大小可减小 CSS 资源的文件大小 下载速度更快这主要是通过将内容从 CSS 源文件(例如空格和其他不可见字符) 将结果导出到新优化的文件:

/* Unminified CSS: */

/* Heading 1 */
h1 {
  font-size: 2em;
  color: #000000;
}

/* Heading 2 */
h2 {
  font-size: 1.5em;
  color: #000000;
}
/* Minified CSS: */
h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}

从最基本的形式来看,CSS 缩减是一项有效的优化, 降低网站的 FCP,在某些情况下甚至可能降低 LCP。这些工具包括 bundlers 可以在生产环境中自动为您执行此优化 build。

移除未使用的 CSS

在呈现任何内容之前,浏览器都需要下载并解析所有 样式表。完成解析所需的时间还包括 当前网页未使用哪些资源如果您使用的捆绑器合并了所有 CSS 单个文件,那么您的用户下载的 CSS 可能比 渲染当前网页所需的资源

若要发现当前网页未使用的 CSS,请使用 Chrome 中的“覆盖率”工具 开发者工具。

<ph type="x-smartling-placeholder">
</ph> Chrome 开发者工具中覆盖率工具的屏幕截图。一个 CSS 文件在其底部窗格中被选中,其中显示了当前页面布局未使用的大量 CSS。 <ph type="x-smartling-placeholder">
</ph> Chrome DevTools 中的覆盖率工具对于检测 CSS(以及 JavaScript)的代码。它可用于拆分 CSS 文件 加载到多个资源中,并由不同的页面加载 提交较大的 CSS 套装,这可能会延迟网页呈现。

移除未使用的 CSS 不仅可以减少下载量,还可以产生双重效果 您就需要优化“渲染树”构建流程,因为浏览器需要 处理的 CSS 规则更少。

<ph type="x-smartling-placeholder">

避免使用 CSS @import 声明

虽然看起来很方便,但您应避免在 CSS 中使用 @import 声明:

/* Don't do this: */
@import url('style.css');

<link> 元素在 HTML 中的工作方式类似,@import 声明 可让您从样式表内导入外部 CSS 资源。通过 这两种方法之间的主要区别在于,HTML <link> 元素 是 HTML 响应的一部分,因此被发现的速度比 CSS 通过 @import 声明下载的文件。

原因在于,若要将 @import 声明 则必须先下载包含它的 CSS 文件。这个 就会产生所谓的“请求链”,在使用 CSS 的情况下,这会延迟 网页首次呈现所需的时间另一个缺点是 使用 @import 声明加载的样式表 预加载扫描器,因此会成为后期发现的阻塞渲染的资源。

<!-- Do this instead: -->
<link rel="stylesheet" href="style.css">

在大多数情况下,您可以使用@import <link rel="stylesheet"> 元素。<link> 元素允许对样式表 与 @import相比,同时下载且减少了总体加载时间 声明,即“连续”下载样式表。

<ph type="x-smartling-placeholder">

内嵌关键 CSS

下载 CSS 文件所需的时间可能会增加网页的 FCP。内嵌 文档 <head> 中的关键样式消除了对 CSS 资源,如果操作正确,则可以缩短 用户的浏览器缓存未准备好。其余 CSS 可加载 异步方式或在 <body> 元素末尾附加。

<ph type="x-smartling-placeholder">
<head>
  <title>Page Title</title>
  <!-- ... -->
  <style>h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}</style>
</head>
<body>
  <!-- Other page markup... -->
  <link rel="stylesheet" href="non-critical.css">
</body>

但这种方法的缺点在于,内嵌大量 CSS 会为初始 HTML 响应。因为 HTML 资源通常不能缓存很长时间或 全部 - 这意味着内嵌的 CSS 不会被缓存,用于 在外部样式表中使用相同的 CSS。测试和衡量网页的 性能,以确保值得做出的取舍。

CSS 演示

JavaScript

Web 的大部分交互方式都是 JavaScript,但也需要付出代价。 传递过多 JavaScript 可能会导致您的网页在网页加载期间响应缓慢 甚至可能导致响应速度问题,降低互动速度。 这也会让用户感到失望

阻塞渲染的 JavaScript

加载不带 deferasync 属性的 <script> 元素时, 浏览器将阻止解析和呈现,直到脚本完成下载、解析和 。同样,内联脚本也会阻止解析器,直到脚本完成解析为止 并执行。

asyncdefer

asyncdefer 允许在不阻止 HTML 的情况下加载外部脚本 解析器,而 type="module" 的脚本(包括内嵌脚本) 已自动推迟。不过,asyncdefer 也有一些差异, 都很重要

<ph type="x-smartling-placeholder">
</ph> 描述各种脚本加载机制,所有机制都根据所使用的各种属性(如 async、defer、type=&#39;module&#39;)详细说明解析器、提取和执行角色以及三者的组合。 <ph type="x-smartling-placeholder">
</ph> 来源:https://html.spec.whatwg.org/multipage/scripting.html

使用 async 加载的脚本会在下载后立即进行解析并执行。 使用 defer 加载的脚本在进行 HTML 文档解析时执行, 完成 - 此事件与浏览器的 DOMContentLoaded 事件同时发生。 此外,async 脚本可能会不按顺序执行,而 defer 脚本 将按照它们在标记中出现的顺序执行。

<ph type="x-smartling-placeholder">

客户端呈现

一般来说,您应避免使用 JavaScript 呈现任何关键内容或 页面的 LCP 元素。这称为客户端呈现,是一种技术 广泛应用于单页应用 (SPA)。

JavaScript 呈现的标记会绕过预加载扫描程序,因为 客户端呈现的标记中包含的标记无法发现。这个 可能会延迟 LCP 映像等关键资源的下载。浏览器 脚本执行完毕后才开始下载 LCP 映像 传递给 DOM反过来,只有在 已发现、下载和解析。我们将此称为关键请求 链,应该避免。

此外,使用 JavaScript 呈现标记更有可能生成 与为响应导航而从服务器下载的标记相比,冗长的任务 请求。大量使用客户端呈现 HTML 可能会对您产生不利影响 互动延迟。在网页的 DOM 为 超大,这在 JavaScript 修改时会触发重要的渲染工作 DOM

缩减大小

与 CSS 类似,缩减 JavaScript 大小会减小脚本资源的文件大小。 这样可以加快下载速度,从而允许浏览器转至 更快地解析和编译 JavaScript 的过程。

此外,与缩减大小相比,JavaScript 缩减 资源(例如 CSS)缩减 JavaScript 的大小后,它并不会直接被删除 但源语言中的符号(例如空格、制表符和注释) JavaScript 会被缩短。此过程有时被称为“污名化”。接收者 请查看以下不同 JavaScript 源代码:

// Unuglified JavaScript source code:
export function injectScript () {
  const scriptElement = document.createElement('script');
  scriptElement.src = '/js/scripts.js';
  scriptElement.type = 'module';

  document.body.appendChild(scriptElement);
}

如果上述 JavaScript 源代码被优化,则结果可能看起来 如以下代码段所示:

// Uglified JavaScript production code:
export function injectScript(){const t=document.createElement("script");t.src="/js/scripts.js",t.type="module",document.body.appendChild(t)}

在前面的代码段中,您可以看到直观易懂的变量 源代码中的 scriptElement 简写为 t。在大型语言模型中 可以显著节省费用, 网站的生产 JavaScript 提供的功能。

如果您使用捆绑器处理网站的源代码, 通常在正式版的项目中自动完成美化词(例如 Terser) 例如,它的可配置性也很高,因此您可以调整 处理更激进的词语,以尽可能节省费用。 不过,任何污名化工具的默认设置通常足以触发警告 在输出规模和保留能力之间保持适当的平衡。

JavaScript 演示

知识测验

在浏览器中加载多个 CSS 文件的最佳方法是什么?

CSS @import 声明。
请重试。
多个 <link> 元素。
正确!

浏览器预加载扫描器有什么作用?

它是一种辅助 HTML 解析器,可检查原始标记以发现 资源,以便更快地发现它们。
正确!
检测到以下元素中的 <link rel="preload"> 元素: HTML 资源。
请重试。

默认情况下,为什么浏览器会暂时阻止对 HTML 的解析 如何下载 JavaScript 资源?

防止出现未设置样式的内容 (FOUC)。
请重试。
因为评估 JavaScript 是一项占用大量 CPU 资源的任务, HTML 解析可为 CPU 提供更多带宽来完成脚本加载。
请重试。
因为脚本可以修改或以其他方式访问 DOM。
正确!

下一篇:使用资源提示协助浏览器

现在,您已经了解了 <head> 元素中加载的资源 影响初始网页加载和各种指标,是时候继续。在未来 单元中讨论了资源提示,以及如何提供有价值的提示, 浏览器以开始加载资源并打开跨源连接 它们的速度会比浏览器快得多。