1. 欢迎
在本实验中,您将使用现有的 Service Worker 获取网站,并将其转换为使用 Workbox。这是渐进式 Web 应用工作坊的一系列配套 Codelab 中的第二个。上一个 Codelab 是离线。本系列还有 6 个 Codelab。
学习内容
- 转换现有 Service Worker 以使用 Workbox
- 为 PWA 添加离线回退
注意事项
- HTML 和 JavaScript 基础知识
所需条件
- 支持 Service Worker 的浏览器
2. 进行设置
首先,克隆或下载完成此 Codelab 所需的起始代码:
如果您克隆了代码库,请确保您位于 pwa03--workbox
分支中。该 ZIP 文件还包含相应分支的代码。
此代码库需要 Node.js 14 或更高版本。获得代码后,在代码的文件夹中通过命令行运行 npm ci
,以安装所需的所有依赖项。然后,运行 npm start
以启动 Codelab 的开发服务器。
源代码的 README.md
文件提供了对所有分发文件的说明。此外,以下是您将在整个 Codelab 中使用的关键现有文件:
密钥文件
service-worker.js
- 应用的服务工作线程文件offline.html
- 在网页不可用时使用的离线 HTML
3. 迁移到 Workbox
查看现有的 service worker,预缓存似乎可以分为两步:
- 在 Service Worker 安装期间缓存相关文件
- 再次使用“仅缓存”策略提供这些文件
index.html
文件和 /
路由仍然适合预缓存,因为此 Web 应用的 HTML 不会发生太大变化,但其他文件(如 CSS 和 JavaScript)可能会发生变化,我们并不希望每次发生变化时都需要经历整个 Service Worker 生命周期。此外,当前的 Service Worker 仅考虑了部分 CSS 和 JavaScript,我们希望涵盖所有这些文件。使用“过时后重新验证”策略缓存这些项更有意义;快速响应,可根据需要在后台更新。
重新审视预缓存
迁移到 Workbox 后,我们无需保留任何现有代码,因此请删除 service-worker.js
中的所有内容。在上一个实验中,我们已将此 Service Worker 设置为可编译,因此我们可以在此处使用 ESModule 导入从其 NPM 模块中引入 Workbox。我们先来回顾一下预缓存。在 service-worker.js
中,添加以下代码:
import { warmStrategyCache } from 'workbox-recipes';
import { CacheFirst } from 'workbox-strategies';
import { registerRoute } from 'workbox-routing';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { ExpirationPlugin } from 'workbox-expiration';
// Set up page cache
const pageCache = new CacheFirst({
cacheName: 'page-cache',
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
new ExpirationPlugin({
maxAgeSeconds: 30 * 24 * 60 * 60,
}),
],
});
warmStrategyCache({
urls: ['/index.html', '/'],
strategy: pageCache,
});
registerRoute(({ request }) => request.mode === 'navigate', pageCache);
说明
如需为 /index.html
和 /
设置预缓存,需要从五个模块中拉取。虽然这看起来可能很多,但此代码比之前编写的代码强大得多。
首先,我们设置一个新的“先缓存”缓存策略,而不是“仅缓存”策略,以便根据需要将其他网页添加到缓存中。为其指定名称,即 page-cache
。Workbox 策略可以采用多种插件,这些插件会影响从缓存中保存和检索内容的生命周期。在此示例中,我们使用了两个插件:Cacheable Response 插件和 Expiration 插件,以确保仅缓存良好的服务器响应,并确保缓存中的每个项目在 30 天后都会被清空。
接下来,使用“预热策略缓存”Workbox 配方,通过 /index.html
和 /
预热策略的缓存。这会在 service worker 的安装事件期间将这些项添加到此缓存中。
最后,注册新路线。任何网页导航请求都将由“先缓存”策略管理,该策略会从缓存或网络中提取内容,然后缓存响应。
缓存资源
在解决了路线预缓存问题后,现在可以重新实现网站资源(即 CSS 和 JavaScript)的缓存。为此,请先将 StaleWhileRevalidate
添加到 workbox-strategies
导入项中,然后将以下代码添加到 Service Worker 的底部:
// Set up asset cache
registerRoute(
({ request }) => ['style', 'script', 'worker'].includes(request.destination),
new StaleWhileRevalidate({
cacheName: 'asset-cache',
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
],
}),
);
说明
此路由首先会确定请求的类型是样式、脚本还是工作器,分别对应于 CSS、JavaScript 或 Web Worker。如果可以,它会使用“过时但需重新验证”策略,尝试先从缓存中提供服务,如果缓存中没有,则回退到网络,同时尝试从网络更新缓存中的版本(如果可能)。与页面策略类似,此策略只会缓存良好的响应。
4. 添加离线回退
将原始的 Service Worker 迁移到 Workbox 后,还需要做一件事,才能防止 PWA 在离线时崩溃:添加离线回退。
您可以为离线时可能无法使用的任何内容设置离线回退,例如网页、字体、CSS、JavaScript、图片等。至少应为所有 PWA 设置页面回退,这样一来,如果用户前往缓存中没有的页面,他们仍会停留在应用的情境中。
Workbox 配方提供了一个离线回退配方,可用于实现此目的!如需使用它,请先将 offlineFallback
添加到 workbox-recipes
导入项中,然后将以下代码添加到 Service Worker 的底部:
// Set up offline fallback
offlineFallback({
pageFallback: '/offline.html',
});
说明
离线后备配方会设置一个仅缓存策略,该策略会使用提供的后备资源进行预热。然后,它会设置一个 Workbox 默认捕获处理程序,捕获任何失败的路由请求(如果缓存中没有任何内容,并且无法访问网络上的某些内容),从缓存中提取相关文件的内容,并在请求继续失败时将其作为内容返回。
5. 恭喜!
您已了解如何使用 Workbox 为路由设置缓存策略,并为 PWA 提供离线回退。
本系列中的下一个 Codelab 是 IndexedDB