本指南将重点介绍 Workbox v6 中引入的破坏性更改,并通过示例说明从 Workbox v5 升级时需要做出哪些更改。
重大更改
工作盒核心
workbox-core
中的 skipWaiting()
方法将不再添加 install
处理程序,等同于仅调用 self.skipWaiting()
。
从现在起,请改用 self.skipWaiting()
,因为 skipWaiting()
可能会在 Workbox v7 中移除。
工作箱预缓存
- 与 HTTP 重定向对应的网址的跨源 HTML 文档不能再用于通过
workbox-precaching
满足导航请求。这种情况通常并不常见。 - 现在,在查找指定请求的预缓存响应时,
workbox-precaching
会忽略fbclid
网址查询参数。 PrecacheController
构造函数现在接受一个具有特定属性(而不是字符串)的对象作为其参数。此对象支持以下属性:cacheName
(与 v5 中传入构造函数的字符串相同)、plugins
(替换了 v5 中的addPlugins()
方法)和fallbackToNetwork
(替换传递给createHandler()
和 v5 中的 `createHandlerBoundTo网址() 的类似选项)。PrecacheController
的install()
和activate()
方法现在仅接受一个参数,该参数应分别设置为相应的InstallEvent
或ActivateEvent
。addRoute()
方法已从PrecacheController
中移除。新的PrecacheRoute
类可用来创建供您随后注册的路由。precacheAndRoute()
方法已从PrecacheController
中移除。(它仍作为由workbox-precaching
模块导出的静态辅助方法而存在。)移除了它,因为PrecacheRoute
可被改用。createMatchCalback()
方法已从PrecacheController
中移除。您可以改用新的PrecacheRoute
。createHandler()
方法已从PrecacheController
中移除。您可以改用PrecacheController
对象的strategy
属性来处理请求。- 已从
workbox-precaching
模块中移除createHandler()
静态导出。在这种情况下,开发者应构建一个PrecacheController
实例并使用其strategy
属性。 - 通过
precacheAndRoute()
注册的路线现在是在后台使用workbox-routing
的Router
类的“真实”路线。如果您交错调用registerRoute()
和precacheAndRoute()
,这可能会导致路由的评估顺序有所不同。
工作箱路由
setDefaultHandler()
方法现在接受与其适用的 HTTP 方法相对应的可选第二个参数,默认为 'GET'
。
- 如果您使用
setDefaultHandler()
且所有请求均为GET
,则无需进行任何更改。 - 如果您有任何非
GET
的请求(POST
、PUT
等),setDefaultHandler()
不会再使这些请求匹配。
构建配置
我们原本不支持使用 workbox-build
和 workbox-cli
中 getManifest
和 injectManifest
模式的 mode
选项,因此该选项已被移除。这不适用于 workbox-webpack-plugin
,因为后者在其 InjectManifest
插件中支持 mode
。
Build Tools 需要 Node.js v10 或更高版本
workbox-webpack-plugin
、workbox-build
或 workbox-cli
不再支持 v10 之前的 Node.js 版本。如果您运行的 Node.js 版本低于 v8,请将运行时更新到受支持的版本。
新改进
工作箱策略
Workbox v6 为第三方开发者引入了一种新方法来定义自己的 Workbox 策略。这可确保第三方开发者能够以完全满足其需求的方式扩展 Workbox。
新的 Strategy 基类
在 v6 中,所有 Workbox 策略类都必须扩展新的 Strategy
基类。为了支持这一点,所有内置策略都已重新编写。
Strategy
基类负责两项主要任务:
- 调用所有策略处理程序通用的插件生命周期回调(例如,何时启动、响应和结束)。
- 创建一个“处理程序”实例,该实例可管理策略处理的每个请求的状态。
新增了“handler”类
我们之前有名为 fetchWrapper
和 cacheWrapper
的内部模块,它们(顾名思义)使用钩子将各种提取和缓存 API 封装到其生命周期中。此机制目前允许插件运行,但尚未提供给开发者。
新的“handler”类 StrategyHandler
将公开这些方法,以便自定义策略可以调用 fetch()
或 cacheMatch()
,并使添加到策略实例的所有插件自动调用。
该类还可让开发者添加他们自己的自定义生命周期回调(这些回调可能特定于他们的策略),并且这些回调“只工作”现有的插件接口。
新插件生命周期状态
在 Workbox v5 中,插件是无状态的。这意味着,如果对 /index.html
的请求同时触发了 requestWillFetch
和 cachedResponseWillBeUsed
回调,那么这两个回调将无法相互通信,甚至不知道它们是由同一请求触发的。
在 v6 中,系统还会向所有插件回调传递一个新的 state
对象。此状态对象对于此特定插件对象和此特定策略调用(即对 handle()
的调用)而言是唯一的。这样一来,开发者可以编写插件,使一个回调可以根据同一插件中另一个回调的操作有条件地执行某些操作(例如,计算运行 requestWillFetch
和运行 fetchDidSucceed
或 fetchDidFail
之间的时间增量)。
新增插件生命周期回调
添加了新的插件生命周期回调,以允许开发者充分利用插件生命周期状态:
handlerWillStart
:在任何处理程序逻辑开始运行之前调用。此回调可用于设置初始处理程序状态(例如,记录开始时间)。handlerWillRespond
:在策略handle()
方法返回响应之前调用。此回调可用于在将该响应返回给路由处理程序或其他自定义逻辑之前对其进行修改。handlerDidRespond
:在策略的handle()
方法返回响应之后调用。此回调可用于记录任何最终响应详细信息,例如,在其他插件作出更改后。handlerDidComplete
:在因调用此策略而添加到事件的所有扩展生命周期 promise 结束后调用。此回调可用于报告需要等待处理程序完成以便计算的任何数据(例如缓存命中状态、缓存延迟时间、网络延迟时间)。handlerDidError
:在处理程序无法提供来自任何来源的有效响应时调用。此回调可用于提供“回退”内容来替代网络错误。
实现自己的自定义策略的开发者无需担心自己调用这些回调;这一切都由新的 Strategy
基类处理。
处理程序的 TypeScript 类型更加准确
各种回调方法的 TypeScript 定义已标准化。对于使用 TypeScript 并自行编写实现或调用处理程序的代码的开发者,这应该会带来更好的体验。
工作框窗口
新增了 messageSkipWaiting() 方法
workbox-window
模块中添加了新方法 messageSkipWaiting()
,以简化通知“正在等待”Service Worker 激活的过程。这样做可以带来一些改进:
- 它使用实际上的标准消息正文
{type: 'SKIP_WAITING'}
调用postMessage()
,Workbox 生成的 Service Worker 会检查该正文以触发skipWaiting()
。 - 它会选择正确的“waiting”Service Worker 来发布此消息,即使它不是注册
workbox-window
的那个 Service Worker。
移除了“external”事件,改为使用 isExternal 属性
workbox-window
中的所有"external"事件均已移除,取而代之的是isExternal
属性设置为true
的“normal”事件。这样一来,关注此差异的开发者仍然可以检测它,而不需要知道的开发者可以忽略该属性。
清理器“为用户提供页面重新加载”诀窍
得益于以上两项更改,“为用户提供页面重新加载”方案可以简化:
MULTI_LINE_CODE_PLACEHOLDER_0
工作箱路由
新的布尔值参数 sameOrigin
会传递给 workbox-routing
中使用的 matchCallback
函数。如果请求针对的是同源网址,则设置为 true
,否则设置为 false。
这可以简化一些常见的样板:
MULTI_LINE_CODE_PLACEHOLDER_1
workbox-expiration 中的 matchOptions
您现在可以在 workbox-expiration
中设置 matchOptions
,然后将其作为 CacheQueryOptions
传递给底层 cache.delete()
调用。(大多数开发者无需执行此操作。)
工作箱预缓存
使用工作箱策略
workbox-precaching
已被重写,以使用 workbox-strategies
作为基数。这应该不会导致任何破坏性更改,并且应该可以使两个模块访问网络和缓存的方式长期保持更好的一致性。
预缓存现在会逐个处理条目,而不是批量处理
workbox-precaching
已更新,因此系统一次只会请求和缓存预缓存清单中的条目,而不是尝试一次性请求并缓存所有条目(让浏览器决定如何进行限制)。
这应该会降低预缓存时出现 net::ERR_INSUFFICIENT_RESOURCES
错误的可能性,同时还应减少预缓存与 Web 应用发出的并发请求之间的带宽争用。
PrecacheFallbackPlugin 可以简化离线回退
workbox-precaching
现在包含一个 PrecacheFallbackPlugin
,用于实现 v6 中新增的 handlerDidError
生命周期方法。
这样一来,当响应不可用时,就可以轻松地将预缓存网址指定为给定策略的“后备”网址。插件将负责为预缓存的网址正确构造正确的缓存键,包括所需的任何修订版本参数。
以下示例展示了如何在 NetworkOnly
策略无法为导航请求生成响应(即显示自定义的离线 HTML 网页)时,使用它通过预缓存的 /offline.html
进行响应:
MULTI_LINE_CODE_PLACEHOLDER_2
运行时缓存中的 precacheFallback
如果您使用 generateSW
来创建 Service Worker,而不是手动编写 Service Worker,则可以使用 runtimeCaching
中新的 precacheFallback
配置选项完成相同的操作:
{
// ... other generateSW config options...
runtimeCaching: [{
urlPattern: ({request}) => request.mode === 'navigate',
handler: 'NetworkOnly',
options: {
precacheFallback: {
// This URL needs to be included in your precache manifest.
fallbackURL: '/offline.html',
},
},
}],
}
获取帮助
我们预计大多数迁移都非常简单。如果您遇到本指南未涵盖的问题,请在 GitHub 上提交问题告知我们。