本指南将重点介绍 Workbox v3 中引入的破坏性更改,并通过示例说明从 Workbox v2 设置升级时需要做出哪些更改。
如果您目前使用的是旧版 sw-precache
/sw-toolbox
组合,并希望首次改用 Workbox,可参阅其他迁移指南,参阅相应的迁移指南。
v3 背景
Workbox 的 v3 版本对现有代码库进行了重大重构。总体目标是:
- 尽可能减小 Workbox 的大小。下载和执行的 Service Worker 运行时代码量减少了。系统会在运行时导入您所使用的特定功能的代码,而不是让所有用户都能使用单体式软件包。
- Workbox 有 CDN。我们提供完全受支持的、基于 Google Cloud Storage 的 CDN 托管,作为访问 Workbox 运行时库的规范选项,让您可以更轻松地启动和运行 Workbox。
- 更好的调试和日志记录功能。调试和日志记录体验得到了极大改进。每当从
localhost
源使用 Workbox,并且从正式版 build 中删除所有日志记录和断言时,调试日志默认处于启用状态。 - 改进了 webpack 插件。
workbox-webpack-plugin
与 webpack 构建流程更紧密地集成,因此当您希望预缓存构建流水线中的所有资源时,可实现零配置的用例。
为了实现这些目标,并清理之前的界面中令人感到尴尬或导致反模式的某些方面,需要在 v3 版本中引入一些破坏性更改。
重大变更
构建配置
以下变更会影响我们共用一组通用配置选项的所有构建工具(workbox-build
、workbox-cli
、workbox-webpack-plugin
)的行为。
'fastest'
处理程序名称之前有效,并且在配置runtimeCaching
时被视为'staleWhileRevalidate'
的别名。此 ID 已失效,开发者应改为直接使用'staleWhileRevalidate'
。- 更新了多个
runtimeCaching.options
属性名称,并进行了额外的参数验证,如果使用无效配置会导致构建失败。如需查看当前支持的选项列表,请参阅runtimeCaching
的文档。
workbox-background-sync
maxRetentionTime
配置参数现在被解释为分钟数,而不是毫秒数。- 现在有一个表示队列名称的必需字符串,在构建插件或独立类时,必须将其作为第一个参数传入。(之前,它是作为选项的属性传入的)。如需了解更新后的 API Surface,请参阅文档。
workbox-broadcast-cache-update
- 现在有一个表示频道名称的必需字符串,在构建插件或独立类时,必须将其作为第一个参数传入。
例如,在 v2 中,您需要按如下方式初始化 Plugin 类:
new workbox.broadcastCacheUpdate.BroadcastCacheUpdatePlugin({
channelName: 'cache-updates',
headersToCheck: ['etag'],
});
v3 中的等效用法如下:
new workbox.broadcastUpdate.Plugin('cache-updates', {headersToCheck: ['etag']});
如需了解更新后的 API Surface,请参阅文档。
workbox-build
- 默认情况下,
glob
模式匹配现在使用选项follow: true
(后跟符号链接)和strict: true
(对“异常”错误的容忍度较低)执行。通过在 build 配置中设置globFollow: false
和/或globStrict: false
,您可以停用其中任一功能并恢复之前的行为。 workbox-build
中的函数都会在返回的响应中返回一个附加属性warnings
。现在允许在 v2 中被视为严重错误的一些场景,但通过warnings
(一个字符串数组)进行报告。
在 v2 中,您可以调用 generateSW
,如下所示:
const workboxBuild = require('workbox-build');
workboxBuild.generateSW({...})
.then(({count, size}) => console.log(`Precached ${count} files, totaling ${size} bytes.`))
.catch((error) => console.error(`Something went wrong: ${error}`));
虽然您可以在 v3 中使用相同的代码,但建议检查是否存在任何 warnings
并记录它们:
const workboxBuild = require('workbox-build');
workboxBuild.generateSW({...})
.then(({count, size, warnings}) => {
for (const warning of warnings) {
console.warn(warning);
}
console.log(`Precached ${count} files, totalling ${size} bytes.`);
})
.catch((error) => console.error(`Something went wrong: ${error}`));
- 在 v2 中编写自己的自定义
ManifestTransform
函数的开发者需要在对象中返回清单数组(即,您应该使用return {manifest: manifestArray};
,而不是return manifestArray;
)。mThis 可让您的插件添加一个可选的warnings
属性,该属性应该是包含非严重警告信息的字符串数组。
如果您使用 v2 编写自定义 ManifestTransform
,则代码如下所示:
const cdnTransform = manifestEntries => {
return manifestEntries.map(entry => {
const cdnOrigin = 'https://example.com';
if (entry.url.startsWith('/assets/')) {
entry.url = cdnOrigin + entry.url;
}
return entry;
});
};
具有 v3 等效项:
const cdnTransform = manifestEntries => {
const manifest = manifestEntries.map(entry => {
const cdnOrigin = 'https://example.com';
if (entry.url.startsWith('/assets/')) {
entry.url = cdnOrigin + entry.url;
}
return entry;
});
return {manifest, warnings: []};
};
getFileManifestEntries()
函数已重命名为getManifest()
,返回的 promise 现在包含有关预缓存网址的其他信息。
v2 中的如下代码:
const manifestEntries = await workboxBuild.getFileManifestEntries({...});
在 v3 中可以重写为:
const {manifestEntries, count, size, warnings} = await workboxBuild.getManifest({...});
// Use manifestEntries like before.
// Optionally, log the new info returned in count, size, warnings.
- 移除了
generateFileManifest()
函数。建议开发者改为调用getManifest()
,并使用其响应以适当的格式将数据写入磁盘。
workbox-cache-expiration
- 插件 API 仍保持不变,大多数开发者最终都将使用该模式。不过,API 发生了重大变化,这会影响将它作为独立类使用的开发者。如需了解更新后的 API Surface,请参阅文档。
workbox-cli
开发者可以使用 --help
标志运行 CLI,以获取所有受支持的参数。
- 不再支持在二进制脚本中使用
workbox-cli
别名。二进制文件现在只能以workbox
的形式访问。 - v2 命令
generate:sw
和inject:manifest
在 v3 中已重命名为generateSW
和injectManifest
。 - 在 v2 中,系统假定默认配置文件(未明确提供配置文件时使用)是当前目录中的
workbox-cli-config.js
。在 v3 中,为workbox-config.js
。
总的来说,这意味着在 v2 中:
$ workbox inject:manifest
运行“注入清单”构建流程,使用从 workbox-cli-config.js
读取的配置,在 v3 中构建:
$ workbox injectManifest
会执行相同的操作,但从 workbox-config.js
读取配置。
工作箱预缓存
precache()
方法之前会执行缓存修改并设置路由以提供缓存条目。现在,precache()
仅修改缓存条目,并且已公开一个新方法addRoute()
,用于注册一个路由以提供这些缓存的响应。如果开发者需要之前的二合一功能,可以改用调用precacheAndRoute()
。- 过去通过
WorkboxSW
构造函数配置的多个选项现在作为options
形参传入workbox.precaching.precacheAndRoute([...], options)
中。参考文档中列出了这些选项的默认值(如果未配置)。 - 默认情况下,系统会自动检查没有任何文件扩展名的网址是否与包含
.html
扩展名的缓存条目匹配。例如,如果针对/path/to/index
(未预缓存)发出请求,并且存在针对/path/to/index.html
的预缓存条目,则系统会使用该预缓存条目。开发者可以在将选项传递到workbox.precaching.precacheAndRoute()
时设置{cleanUrls: false}
来停用此新行为。 workbox-broadcast-update
将不再自动配置为公布预缓存资产的缓存更新。
以下代码(在 v2 中):
const workboxSW = new self.WorkboxSW({
directoryIndex: 'index.html',
ignoreUrlParametersMatching: [/^utm_/],
precacheChannelName: 'precache-updates',
});
workboxSW.precache([...]);
具有 v3 等效项:
workbox.precaching.addPlugins([
new workbox.broadcastUpdate.Plugin('precache-updates')
]);
workbox.precaching.precacheAndRoute([...], {
cleanUrls: false,
directoryIndex: 'index.html',
ignoreUrlParametersMatching: [/^utm_/],
});
工作箱路由
- 之前通过 WorkboxSW 对象的
workbox.router.*
命名空间使用workbox-routing
的开发者需要切换到新的命名空间workbox.routing.*
。 - 现在,系统会按照“先注册成功”的顺序评估路线。这与 v2 中使用的
Route
计算顺序相反,其中最后注册的Route
优先。 ExpressRoute
类,以及对“Express-style”的支持通配符已移除。这会大幅缩减workbox-routing
的大小。用作workbox.routing.registerRoute()
第一个参数的字符串现在将被视为完全匹配。通配符或部分匹配应由RegExp
处理,使用与请求网址的部分或全部匹配的任何RegExp
均可触发路由。- 移除了
Router
类的addFetchListener()
辅助方法。开发者可以明确添加自己的fetch
处理程序,也可以使用workbox.routing
提供的接口(该接口会为开发者隐式创建fetch
处理程序)。 - 移除了
registerRoutes()
和unregisterRoutes()
方法。针对单个Route
运行的这些方法的版本保持不变,需要一次性注册或取消注册多个路由的开发者应改为对registerRoute()
或unregisterRoute()
进行一系列调用。
以下代码(在 v2 中):
const workboxSW = new self.WorkboxSW();
workboxSW.router.registerRoute(
'/path/with/.*/wildcard/',
workboxSW.strategies.staleWhileRevalidate()
);
workboxSW.router.registerRoute(
new RegExp('^https://example.com/'),
workboxSW.strategies.networkFirst()
);
具有 v3 等效项:
workbox.routing.registerRoute(
new RegExp('^https://example.com/'),
workbox.strategies.networkFirst()
);
workbox.routing.registerRoute(
new RegExp('^/path/with/.*/wildcard'),
workbox.strategies.staleWhileRevalidate()
);
workbox-strategies(以前称为“workbox-runtime-caching”)
workbox-runtime-caching
模块现已正式更名为workbox-strategies
,并已采用新名称发布于npm
。- 在策略中使用缓存过期时间而不同时提供缓存名称将失效。在 v2 中,可以做到以下几点:
workboxSW.strategies.staleWhileRevalidate({
cacheExpiration: {maxEntries: 50},
});
这会导致默认缓存中的条目过期,这属于意外情况。在 v3 中,缓存名称 为必填项:
workboxSW.strategies.staleWhileRevalidate({
cacheName: 'my-cache',
plugins: [new workbox.expiration.Plugin({maxEntries: 50})],
});
cacheWillMatch
生命周期方法已重命名为cachedResponseWillBeUsed
。开发者应该不会轻易看到这项更改,除非他们自己编写了能够响应cacheWillMatch
的插件。- 配置策略时用于指定插件的语法已经更改。每个插件都需要在策略配置的
plugins
属性中明确列出。
以下代码(在 v2 中):
const workboxSW = new self.WorkboxSW();
const networkFirstStrategy = workboxSW.strategies.networkFirst({
cacheName: 'my-cache',
networkTimeoutSeconds: 5,
cacheExpiration: {
maxEntries: 50,
},
cacheableResponse: {
statuses: [0, 200],
},
});
具有 v3 等效项:
const networkFirstStrategy = workbox.strategies.networkFirst({
cacheName: 'my-cache',
networkTimeoutSeconds: 5,
plugins: [
new workbox.expiration.Plugin({maxEntries: 50}),
new workbox.cacheableResponse.Plugin({statuses: [0, 200]}),
],
});
有关详情,请参阅“使用插件”指南。
Workbox-sw
- 在后台,
workbox-sw
已被重写为轻量级“加载器”接口,该接口需要进行一些基本配置,并负责提取运行时所需的其他模块。开发者不会构建WorkboxSW
类的新实例,而是与在全局命名空间中自动公开的现有实例进行交互。
之前是在 v2 中:
importScripts('<path to workbox-sw>/importScripts/workbox-sw.prod.v2.1.3.js');
const workbox = new WorkboxSW({
skipWaiting: true,
clientsClaim: true,
// etc.
});
workbox.router.registerRoute(...);
在 v3 中,您只需导入 workbox-sw.js
脚本,即可自动在全局命名空间中以 workbox
的形式提供可供使用的实例:
importScripts('<path to workbox-sw>/3.0.0/workbox-sw.js');
// workbox is implicitly created and ready for use.
workbox.routing.registerRoute(...);
skipWaiting
和clientsClaim
不再是传递给WorkboxSW
构造函数的选项。而是将它们更改为了workbox.clientsClaim()
和workbox.skipWaiting()
方法。- 之前在 v2 构造函数中支持的
handleFetch
选项在 v3 中不再受支持。如果开发者需要类似功能来测试其 Service Worker,而不调用任何提取处理程序,则可以使用“Bypass for network”选项。
workbox-webpack-plugin
插件经过了大幅重写,在很多情况下,可以在“零配置”下使用模式。如需了解更新后的 API Surface,请参阅文档。
- API 现在公开了两个类:
GenerateSW
和InjectManifest
。这使得模式之间的切换变得明确,而在 v2 行为中,行为因swSrc
的存在而发生变化。 - 默认情况下,系统会预缓存 webpack 编译流水线中的资源,因此不再需要配置
globPatterns
。继续使用globPatterns
的唯一原因是,您需要预缓存 webpack build 中未包含的资源。一般来说,迁移到 v3 插件时,您应先移除所有以前的基于glob
的配置,并仅在特别需要时重新添加。
获取帮助
我们预计大多数迁移都非常简单。如果您遇到本指南未涵盖的问题,请在 GitHub 上提交问题告知我们。