预提取、预渲染和 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 在用户与网页互动时动态预提取资源。

prefetch 受所有现代浏览器(Safari 除外)支持,在 Safari 中,该属性可通过标志启用。如果您非常需要以适用于所有浏览器的方式为网站预先加载资源,并且您正在使用 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 投机性地预提取资源。服务工作线程预缓存可以使用 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',
]);

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

由于服务工作线程得到广泛支持,因此您可以在任何需要使用服务工作线程预缓存的新型浏览器上使用它。

知识测验

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

无压力
中等。
高。

提取网页与预渲染网页之间有何区别?

它们大致相同,只是预渲染会获取网页的所有子资源,而预提取不会。
虽然网页的预提取和预渲染都会获取网页及其所有子资源,但预提取只会检索网页及其所有资源,而预渲染则更进一步,会在后台渲染整个网页,直到用户导航到该网页。

Service Worker 缓存和 HTTP 缓存相同。

错误
正确

接下来:Web 工作器概览

现在,您已经了解预提取、预渲染和服务工作线程预缓存在加快未来网页的导航速度方面有多么有用,因此可以根据实际情况做出明智的决定,了解这些技术对您的网站及其用户有何益处。

接下来,简要介绍了 Web Worker,以及它们如何将耗时的工作从主线程中分离出来,从而为主线程留出更多空间来处理用户互动。如果您曾想知道可以做些什么来为主要线程提供更多喘息空间,那么接下来的两个模块值得您花时间学习!