本指南重点介绍了 Workbox v4 中引入的重大变更,并通过示例说明了从 Workbox v3 升级时需要进行哪些更改。
重大变更
workbox-precaching
预缓存条目的命名惯例已更新。现在,对于网址需要修订信息的条目(即在预缓存清单中包含 revision
字段的条目),系统会将该修订信息作为缓存键的一部分存储在附加到原始网址的特殊 __WB_REVISION__
网址查询参数中。(以前,此类信息是使用 IndexedDB 与缓存键分开存储的。)
如果开发者通过 workbox.precaching.precacheAndRoute()
(最常见的用例)利用预缓存功能,则无需对其服务工件配置进行任何更改;升级到 Workbox v4 后,用户的缓存资源将自动迁移到新的缓存键格式,今后,预缓存资源将继续以与之前相同的方式提供。
直接使用缓存键
某些开发者可能需要在 workbox.precaching.precacheAndRoute()
上下文之外直接访问预缓存条目。例如,您可以预缓存某张图片,以便在无法从网络提取实际图片时将其用作“后备”响应。
如果您以这种方式使用预缓存资源,从 Workbox v4 开始,您需要执行额外的步骤才能将原始网址转换为可用于读取缓存条目的相应缓存键。只需调用 workbox.precaching.getCacheKeyForURL(originURL)
即可做到这一点。
例如,如果您知道 'fallback.png'
已预缓存:
const imageFallbackCacheKey =
workbox.precaching.getCacheKeyForURL('fallback.png');
workbox.routing.setCatchHandler(({event}) => {
switch (event.request.destination) {
case 'image':
return caches.match(imageFallbackCacheKey);
break;
// ...other fallback logic goes here...
}
});
清理旧的预缓存数据
对 Workbox v4 中的预缓存所做的更改意味着,由旧版 Workbox 创建的旧版预缓存不兼容。默认情况下,这些资源会保持不变。如果您从 Workbox v3 升级到 Workbox v4,则所有预缓存资源都会有两个副本。
为避免出现这种情况,您可以直接向服务工件添加对 workbox.precaching.cleanupOutdatedCaches()
的调用,或者在 GenerateSW
模式下使用构建工具时设置新的 cleanupOutdatedCaches: true
选项。由于缓存清理逻辑根据缓存命名规范进行操作,以查找较旧的预缓存,而且开发者可以选择替换这些规范,因此我们出于安全考虑而出错,默认情况下未启用此功能。
如果开发者在使用此功能时遇到任何问题(例如删除时出现误报),我们建议他们告诉我们。
参数大小写
我们重命名了两个可传递给 workbox.precaching.precacheAndRoute()
和 workbox.precaching.addRoute()
的可选参数,以标准化我们的整体大小写惯例。ignoreUrlParametersMatching
现已改为 ignoreURLParametersMatching
,cleanUrls
现已改为 cleanURLs
。
工作箱策略
在 workbox-strategies
中创建处理程序实例的方法大致有两种。我们即将弃用 factory 方法,改为显式调用策略的构造函数。
// This factory method syntax has been deprecated:
const networkFirstStrategy = workbox.strategies.networkFirst({...});
// Instead, use the constructor directly:
// (Note that the class name is Uppercase.)
const networkFirstStrategy = new workbox.strategies.NetworkFirst({...});
虽然工厂方法语法在 v4 中仍然有效,但使用它会记录警告,我们建议开发者在未来的 v5 版本中移除支持之前提前进行迁移。
workbox-background-sync
workbox.backgroundSync.Queue
类已重写,可让开发者更灵活地控制请求如何添加到队列并重放。
在 v3 中,Queue
类只有一种方法来向队列添加请求(addRequest()
方法),但没有任何方法可以修改队列或移除请求。
在 v4 中,已移除 addRequests()
方法,并添加了以下类似数组的方法:
pushRequest()
popRequest()
shiftRequest()
unshiftRequest()
在 v3 中,Queue
类还接受了几个回调,让您能够观察请求重放的时间(requestWillEnqueue
、requestWillReplay
、queueDidReplay
),但大多数开发者发现,除了观察之外,他们还希望控制队列的重放方式,包括能够动态修改、重新排序甚至取消单个请求。
在 v4 中,这些回调已被移除,取而代之的是单个 onSync
回调,每当浏览器尝试重放时,系统都会调用该回调。默认情况下,onSync
回调会调用 replayRequests()
,但如果您需要更好地控制重放过程,则可以使用上面列出的类数组方法以您喜欢的方式重放队列。
以下是自定义重放逻辑示例:
const queue = new workbox.backgroundSync.Queue('my-queue-name', {
onSync: async ({queue}) => {
let entry;
while ((entry = await this.shiftRequest())) {
try {
await fetch(entry.request);
} catch (error) {
console.error('Replay failed for request', entry.request, error);
await this.unshiftRequest(entry);
return;
}
}
console.log('Replay complete!');
},
});
同样,workbox.backgroundSync.Plugin
类接受与 Queue
类相同的参数(因为它会在内部创建 Queue
实例),因此也以相同的方式发生了变化。
工作区过期时间
npm
软件包已重命名为 workbox-expiration
,以与其他模块使用的命名惯例保持一致。此软件包的功能等同于旧版 workbox-cache-expiration
软件包,后者现已废弃。
workbox-broadcast-update
npm
软件包已重命名为 workbox-broadcast-update
,以与其他模块使用的命名惯例保持一致。此软件包在功能上等同于现已废弃的旧版 workbox-broadcast-cache-update
软件包。
workbox-core
在 Workbox v3 中,您可以通过 workbox.core.setLogLevel()
方法控制日志级别的详细程度,方法是传递 workbox.core.LOG_LEVELS
枚举中的某个值。您还可以通过 workbox.core.logLevel
读取当前的日志级别。
在 Workbox v4 中,所有这些选项都已移除,因为所有现代开发者工具现在都提供丰富的日志过滤功能(请参阅 Chrome 开发者工具的过滤控制台输出)。
workbox-sw
之前直接在 workbox
命名空间(对应于 workbox-sw
模块)上公开的两个方法已改为移至 workbox.core
。workbox.skipWaiting()
已变为 workbox.core.skipWaiting()
,同样,workbox.clientsClaim()
已变为 workbox.core.clientsClaim()
。
构建工具配置
可传递到 workbox-cli、workbox-build 或 workbox-webpack-plugin 的某些选项的命名已更改。每当在选项名称中使用“Url”时,“网址”已被废弃。这意味着,以下选项名称是首选:
dontCacheBustURLsMatching
ignoreURLParametersMatching
modifyURLPrefix
templatedURLs
这些选项名称的“网址”变体在 v4 中仍然有效,但会导致显示警告消息。我们建议开发者在 v5 发布之前进行迁移。
新功能
workbox-window
新的 workbox-window
模块可简化 Service Worker 注册和检测更新的过程,并为 Service Worker 中运行的代码与 Web 应用的 window
上下文中运行的代码提供标准通信方式。
虽然使用 workbox-window
并非强制性要求,但我们希望开发者能发现它的实用性,并在适当情况下考虑迁移手写逻辑以使用它。如需详细了解如何使用 workbox-window
,请参阅模块指南。
迁移示例
如需查看从 Workbox v3 迁移到 v4 的实际示例,请参阅此拉取请求。
获取帮助
我们预计大多数迁移都很简单。如果您遇到本指南未涵盖的问题,请在 GitHub 上提交问题,告知我们。