从 Workbox v5 迁移到 v6

本指南将重点介绍 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网址() 的类似选项)。
  • PrecacheControllerinstall()activate() 方法现在仅接受一个参数,该参数应分别设置为相应的 InstallEventActivateEvent
  • addRoute() 方法已从 PrecacheController 中移除。新的 PrecacheRoute 类可用来创建供您随后注册的路由。
  • precacheAndRoute() 方法已从 PrecacheController 中移除。(它仍作为由 workbox-precaching 模块导出的静态辅助方法而存在。)移除了它,因为 PrecacheRoute 可被改用。
  • createMatchCalback() 方法已从 PrecacheController 中移除。您可以改用新的 PrecacheRoute
  • createHandler() 方法已从 PrecacheController 中移除。您可以改用 PrecacheController 对象的 strategy 属性来处理请求。
  • 已从 workbox-precaching 模块中移除 createHandler() 静态导出。在这种情况下,开发者应构建一个 PrecacheController 实例并使用其 strategy 属性。
  • 通过 precacheAndRoute() 注册的路线现在是在后台使用 workbox-routingRouter 类的“真实”路线。如果您交错调用 registerRoute()precacheAndRoute(),这可能会导致路由的评估顺序有所不同。

工作箱路由

setDefaultHandler() 方法现在接受与其适用的 HTTP 方法相对应的可选第二个参数,默认为 'GET'

  • 如果您使用 setDefaultHandler() 且所有请求均为 GET,则无需进行任何更改。
  • 如果您有任何非 GET 的请求(POSTPUT 等),setDefaultHandler() 不会再使这些请求匹配。

构建配置

我们原本不支持使用 workbox-buildworkbox-cligetManifestinjectManifest 模式的 mode 选项,因此该选项已被移除。这不适用于 workbox-webpack-plugin,因为后者在其 InjectManifest 插件中支持 mode

Build Tools 需要 Node.js v10 或更高版本

workbox-webpack-pluginworkbox-buildworkbox-cli 不再支持 v10 之前的 Node.js 版本。如果您运行的 Node.js 版本低于 v8,请将运行时更新到受支持的版本

新改进

工作箱策略

Workbox v6 为第三方开发者引入了一种新方法来定义自己的 Workbox 策略。这可确保第三方开发者能够以完全满足其需求的方式扩展 Workbox。

新的 Strategy 基类

在 v6 中,所有 Workbox 策略类都必须扩展新的 Strategy 基类。为了支持这一点,所有内置策略都已重新编写。

Strategy 基类负责两项主要任务:

  • 调用所有策略处理程序通用的插件生命周期回调(例如,何时启动、响应和结束)。
  • 创建一个“处理程序”实例,该实例可管理策略处理的每个请求的状态。

新增了“handler”类

我们之前有名为 fetchWrappercacheWrapper 的内部模块,它们(顾名思义)使用钩子将各种提取和缓存 API 封装到其生命周期中。此机制目前允许插件运行,但尚未提供给开发者。

新的“handler”类 StrategyHandler 将公开这些方法,以便自定义策略可以调用 fetch()cacheMatch(),并使添加到策略实例的所有插件自动调用。

该类还可让开发者添加他们自己的自定义生命周期回调(这些回调可能特定于他们的策略),并且这些回调“只工作”现有的插件接口。

新插件生命周期状态

在 Workbox v5 中,插件是无状态的。这意味着,如果对 /index.html 的请求同时触发了 requestWillFetchcachedResponseWillBeUsed 回调,那么这两个回调将无法相互通信,甚至不知道它们是由同一请求触发的。

在 v6 中,系统还会向所有插件回调传递一个新的 state 对象。此状态对象对于此特定插件对象和此特定策略调用(即对 handle() 的调用)而言是唯一的。这样一来,开发者可以编写插件,使一个回调可以根据同一插件中另一个回调的操作有条件地执行某些操作(例如,计算运行 requestWillFetch 和运行 fetchDidSucceedfetchDidFail 之间的时间增量)。

新增插件生命周期回调

添加了新的插件生命周期回调,以允许开发者充分利用插件生命周期状态:

  • 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 上提交问题告知我们。