预取、预渲染和 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 预取文档。Speculation Rules 定义为包含在页面 HTML 中的 JSON 对象,或通过 JavaScript 动态添加

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

JSON 对象描述了一个或多个操作(目前仅支持 prefetchprerender)以及与该操作关联的 URL 列表。在前面的 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 缓存中,它们几乎可以在请求时立即获取。

Shows service worker caching flow from page, to service worker, to cache.
仅缓存策略仅在 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.jsworkbox-precaching 中提供的 precacheAndRoute 方法会自动注册必要的处理程序,以确保在必要时始终从 Service Worker API 获取预缓存的资源。

由于 Service Worker 得到广泛支持,因此您可以在任何需要它的现代浏览器上使用 Service Worker 预缓存。

测试您的知识

prefetch 提示发生在什么优先级?

高。
再试一次。
中。
再试一次。
低。
正确!

页面和预渲染页面之间有什么区别?

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

Service Worker 缓存和 HTTP 缓存是相同的。

正确
再试一次。
错误
正确!

接下来:Web Worker 概述

现在您已经了解了预取、预渲染和 Service Worker 预缓存在加速未来页面导航方面的优势,您就可以就如何使您的网站及其用户受益做出一些明智的决定。

接下来,将概述 Web Worker,以及它们如何将昂贵的工作从主线程中移出,并为主线程提供更多用户交互的喘息空间。如果您曾经想知道可以做些什么来为主线程提供更多喘息空间,那么接下来的两个模块值得您花时间学习!