预提取、预渲染和 Service Worker 预缓存

在前几个单元中,您了解了延迟加载 JavaScript延迟加载图片和 <iframe> 元素等概念。延迟加载资源会在页面初始加载期间减少网络用量和 CPU 使用率,方法是在需要资源的位置下载资源,而不是预先加载资源,以免资源被闲置。这可以缩短初始网页加载时间,但如果驱动后续互动所需的资源在发生时尚未加载,则后续互动可能会出现延迟。

例如,如果页面包含自定义日期选择器,您可以将日期选择器的资源延迟到用户与该元素互动之后。但是,按需加载日期选择器的资源可能会导致延迟(可能略微),但也可能不会发生,具体取决于用户的网络连接和/或设备功能,直至资源下载、解析并可供执行。

这有点棘手 - 您不想因为加载未使用的资源而浪费带宽,但延迟互动和后续网页加载可能也不理想。幸运的是,您可以使用多种工具来在这两种极端之间取得更好的平衡。本单元介绍了可用于实现这一目标的一些技术,例如预提取资源、预渲染整个页面以及使用 Service Worker 预缓存资源。

近期以低优先级预提取近期所需的资源

您可以使用 <link rel="prefetch"> 资源提示提前提取资源(包括图片、样式表或 JavaScript 资源)。prefetch 提示用于告知浏览器在不久的将来可能需要某个资源。

指定 prefetch 提示后,浏览器可能会以最低优先级发起对该资源的请求,以避免与当前页面所需的资源发生争用。

预提取资源可以改善用户体验,因为用户无需等待近期所需的资源下载完毕,因为可以在需要时立即从磁盘缓存中检索这些资源。

<head>
  <!-- ... -->
  <link rel="prefetch" as="script" href="/date-picker.js">
  <link rel="prefetch" as="style" href="/date-picker.css">
  <!-- ... -->
</head>

上述 HTML 代码段会告知浏览器,它可以在 date-picker.jsdate-picker.css 空闲后预提取。您也可以在用户与 JavaScript 中的页面互动时动态预提取资源。

除 Safari 外,所有现代浏览器都支持 prefetch,后者通过标志提供。如果您迫切需要以适用于所有浏览器的方式预先加载网站的资源,并且您使用了 Service Worker,请阅读本单元中有关使用 Service Worker 预缓存资源的后续部分。

预提取网页,加快日后的导航速度

您还可以通过在指向某个 HTML 文档时指定 as="document" 属性来预提取网页及其所有子资源:

<link rel="prefetch" href="/page" as="document">

当浏览器处于空闲状态时,可能会为 /page 发起低优先级请求。

在基于 Chromium 的浏览器中,您可以使用 Speculation Rules API 预提取文档。推测规则定义为包含在网页的 HTML 中的 JSON 对象,或通过 JavaScript 动态添加:

<script type="speculationrules">
{
  "prefetch": [{
    "source": "list",
    "urls": ["/page-a", "/page-b"]
  }]
}
</script>

JSON 对象描述一项或多项操作(目前仅支持 prefetchprerender),以及与该操作相关联的网址列表。在上述 HTML 代码段中,系统会指示浏览器预提取 /page-a/page-b。与 <link rel="prefetch"> 类似,推测规则是浏览器在某些情况下可能会忽略的提示。

Quicklink 等库会在网页在用户视口中可见时,动态预提取或预渲染网页链接,从而改进网页导航。与预先抓取页面上的所有链接相比,这可以提高用户最终导航到该页面的可能性。

预渲染页面

除了预提取资源之外,还可以提示浏览器在用户导航到某个网页之前预呈现该网页。这种做法几乎可以即时加载网页,因为系统会在后台提取和处理网页及其资源。当用户导航到相应页面后,系统会将该页面置于前台。

Speculation Rules API 支持预渲染:

<script type="speculationrules">
{
  "prerender": [
    {
      "source": "list",
      "urls": ["/page-a", "page-b"]
    }
  ]
}
</script>

预提取和预渲染演示

Service Worker 预缓存

您还可以使用 Service Worker 推测性地预提取资源。Service Worker 预缓存可以使用 Cache API 提取和保存资源,这样浏览器无需访问网络即可使用 Cache API 处理请求。Service Worker 预缓存使用一种非常有效的 Service Worker 缓存策略,称为“仅缓存”策略。这种模式非常有效,因为将资源放入 Service Worker 缓存后,可在收到请求时几乎即时提取这些资源。

显示 Service Worker 从页面到 Service Worker 再到缓存的缓存流程。
仅缓存策略仅在 Service Worker 安装期间从网络中检索符合条件的资源。安装后,缓存的资源只能从 Service Worker 缓存中检索。

如需使用 Service Worker 预缓存资源,您可以使用 Workbox。不过,如果您愿意,也可以编写自己的代码来缓存一组预定文件。无论采用哪种方式,您决定使用 Service Worker 预缓存资源,都必须了解预缓存发生在Service Worker 安装之后。安装完成后,就可以在 Service Worker 在您的网站上控制的任何页面上检索预缓存的资源。

Workbox 使用预缓存清单来确定应预缓存的资源。预缓存清单是一个文件和版本控制信息列表,可作为要预缓存的资源的“可信来源”。

[{  
    url: 'script.ffaa4455.js',
    revision: null
}, {
    url: '/index.html',
    revision: '518747aa'
}]

上述代码是一个示例清单,其中包含 script.ffaa4455.js/index.html 这两个文件。如果资源在文件本身中包含版本信息(称为文件哈希),则 revision 属性可以保留为 null,因为文件已进行版本控制(例如,上述代码中 script.ffaa4455.js 资源的 ffaa4455 属性)。对于无版本控制的资源,可以在构建时为其生成修订版本。

设置后,Service Worker 可用于预缓存静态页面或其子资源,以加快后续页面导航的速度。

workbox.precaching.precacheAndRoute([
  '/styles/product-page.ac29.css',
  '/styles/product-page.39a1.js',
]);

例如,在电子商务商品详情页面上,可以使用 Service Worker 预缓存呈现商品详情页面所需的 CSS 和 JavaScript,以便更快地导航到商品详情页面。在上述示例中,product-page.ac29.cssproduct-page.39a1.js 被预缓存。workbox-precaching 中提供的 precacheAndRoute 方法会自动注册所需的处理程序,以确保在必要时从 Service Worker API 提取预缓存的资源。

由于 Service Worker 受到广泛支持,因此您可以根据情况在任何现代浏览器上使用 Service Worker 预缓存。

知识测验

什么优先级才会出现 prefetch 提示?

过高。
请重试。
中等。
请重试。
低。
正确!

提取和预呈现网页有何区别?

虽然网页的预提取和预渲染都会获取网页及其所有子资源,但预提取只会检索网页及其所有资源,而预渲染则更进一步,它会将整个网页呈现为背景,直到用户导航到该网页为止。
正确!
两者基本相同,只有预渲染会获取网页的所有子资源,而预提取则不会。
请重试。

Service Worker 缓存和 HTTP 缓存相同。

正确
请重试。
False
正确!

下一篇:Web Worker 概览

现在,您已经知道预提取、预渲染和 Service Worker 预缓存在加快未来网页的导航速度方面会带来多大好处,因此您可以在判断这对您的网站及其用户带来哪些好处时做出明智的决策。

接下来,我们将概述 Web 工作器,并说明它们如何能够从主线程中减少开销高昂的工作,为主线程提供更多的用户互动空间。如果您想知道怎样才能为主线程提供更多留白空间,那么接下来的两个模块一定值得您花时间学习!