使用 Workbox 预缓存

预缓存是 Service Worker 中最常见的做法之一,无论您选择哪种 Workbox 构建工具,Workbox 都为完成这项重要任务提供了很大的灵活性。在本指南中,您将了解如何使用 generateSWinjectManifest 预缓存资源,以及其中哪些方法可能最适合您的项目。

使用 generateSW 进行预缓存

generateSW 是在 Workbox 中预缓存资产的最简单方法。使用 generateSW 需要注意的一点是,您不会编写自己的 Service Worker,而是要求 Workbox 为您生成一个 Service Worker。不过,您可以通过各种配置选项来影响其行为。

默认情况下,generateSW 会执行不同的操作,具体取决于您使用的构建工具。使用 workbox-webpack-plugin 时,您无需指定任何配置选项。默认情况下,插件将预缓存 webpack 包含在其依赖关系图中的所有内容,并将名为 service-worker.js 的 Service Worker 写入 output.path 指定的目录

另一方面,如果您使用 workbox-buildworkbox-cli,则默认情况下,系统只会预缓存从本地文件系统读取的 HTML、CSS 和 JavaScript 资源。在配置方面,您必须在 generateSW 配置中指定 swDestglobDirectory 选项,预缓存才能正常运行。您可能还需要配置影响 Service Worker 行为的其他选项,因此请通读文档。

使用 injectManifest 进行预缓存

使用 injectManifest 不像使用 generateSW 那么简单,但您需要牺牲易用性来提高灵活性。generateSW 会为您处理整个 Service Worker 生成过程,injectManifest 会将您编写的 Service Worker 作为其来源,并注入要预缓存的网址列表,同时让其余 Service Worker 保持不变。

使用 injectManifest 时,您需要负责连接预缓存逻辑。injectManifest 在检查输入 Service Worker 时,会查找特殊的 self.__WB_MANIFEST 变量,并将其替换为预缓存清单。如果此变量不存在,injectManifest 会抛出错误。

您可以使用其他配置选项调整预缓存清单中的条目列表。

并列比较

点击以下每个标签页即可比较 generateSWinjectManifest 方法的用法:

由于 generateSW 会生成 Service Worker,因此您只需指定配置。下面是一个使用 workbox-build 的示例:

// build-sw.js
import {generateSW} from 'workbox-build';

generateSW({
  swDest: './dist/sw.js',
  globDirectory: './dist',
  globPatterns: [
    '**/*.js',
    '**/*.css',
    '**/*.svg'
  ]
});

然后,在命令行中使用 Node 构建 Service Worker:

node build-sw.js

由于 injectManifest 需要源 Service Worker,因此一个最简可行的示例需要源 Service Worker 文件。如果只需要预缓存,该输入 Service Worker 可能如下所示:

import {precacheAndRoute} from 'workbox-precaching';

precacheAndRoute(self.__WB_MANIFEST);

请记下 self.__WB_MANIFEST 字符串。这是 Workbox 用预缓存清单替换的占位符。以下是此用例的有效配置:

// build-sw.js
import {injectManifest} from 'workbox-build';

injectManifest({
  swSrc: './src/sw.js',
  swDest: './dist/sw.js',
  globDirectory: './dist',
  globPatterns: [
    '**/*.js',
    '**/*.css',
    '**/*.svg'
  ]
});

如果您有复杂的要求(例如高级路由、自定义缓存策略或 generateSW 提供的选项未涵盖的其他内容),则建议使用 injectManifest

总结

与必须自行管理预缓存相比,在 Workbox 中进行预缓存要简单得多,尤其是在考虑捆绑器编译的版本化资源的情况下。不过,预缓存并不是您需在 Service Worker 中唯一要做的事情。在继续学习的过程中,您将学习其他技术,例如运行时缓存。