本指南重点介绍了 Workbox v6 中引入的重大变更,并通过示例说明了从 Workbox v5 升级时需要进行哪些更改。
重大变更
workbox-core
workbox-core
中的 skipWaiting()
方法将不再添加 install
处理脚本,而等同于仅调用 self.skipWaiting()
。
从现在开始,请改用 self.skipWaiting()
,因为 skipWaiting()
可能会在 Workbox v7 中被移除。
workbox-precaching
- 与 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
属性来处理请求。createHandler()
静态导出已从workbox-precaching
模块中移除。取而代之的是,开发者应构造PrecacheController
实例并使用其strategy
属性。- 在
precacheAndRoute()
中注册的路线现在是“真实”路线,在后台使用workbox-routing
的Router
类。如果您交错调用registerRoute()
和precacheAndRoute()
,这可能会导致路由的评估顺序不同。
workbox-routing
setDefaultHandler()
方法现在接受与其适用的 HTTP 方法相对应的可选第二个参数,默认为 'GET'
。
- 如果您使用
setDefaultHandler()
且所有请求均为GET
,则无需进行任何更改。 - 如果您有任何非
GET
的请求(POST
、PUT
等),setDefaultHandler()
将不再导致这些请求匹配。
构建配置
workbox-build
和 workbox-cli
中适用于 getManifest
和 injectManifest
模式的 mode
选项不受支持,已被移除。这不适用于 workbox-webpack-plugin
,因为后者在其 InjectManifest
插件中支持 mode
。
构建工具需要 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 并编写自己的代码来实现或调用处理程序的开发者带来更好的体验。
workbox-window
新的 messageSkipWaiting() 方法
workbox-window
模块中添加了新方法 messageSkipWaiting()
,以简化告知“等待中”服务工作器激活的过程。这带来了一些改进:
- 它会使用事实上的标准消息正文
{type: 'SKIP_WAITING'}
调用postMessage()
,Workbox 生成的服务工件会检查该消息正文,以触发skipWaiting()
。 - 它会选择正确的“等待”服务工件来发布此消息,即使该服务工件与
workbox-window
注册的服务工件不同也是如此。
移除了“external”事件,改用 isExternal 属性
workbox-window
中的所有“外部”事件均已移除,取而代之的是将 isExternal
属性设为 true
的“正常”事件。这样一来,关心此区别的开发者仍然可以检测到此区别,而不需要了解此区别的开发者可以忽略此属性。
更简洁的“为用户提供网页重新加载”方案
得益于以上两项更改,“向用户提供页面重新加载”方案可以简化:
MULTI_LINE_CODE_PLACEHOLDER_0
workbox-routing
系统会将一个新的布尔值参数 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
已重写,以使用 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
为您创建服务工件,而不是手动编写服务工件,则可以使用 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 上提交问题,告知我们。