从 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(替换 v5 中传递给 createHandler() 和 `createHandlerBoundTo网址() 的类似选项)。
  • 现在,PrecacheControllerinstall()activate() 方法正好接受一个参数,这些参数应分别设置为相应的 InstallEventActivateEvent
  • addRoute() 方法已从 PrecacheController 中移除。取而代之的是,新的 PrecacheRoute 类可用于创建您随后可以注册的路由。
  • precacheAndRoute() 方法已从 PrecacheController 中移除。(它仍作为 workbox-precaching 模块导出的静态辅助方法存在。)由于可以改用“PrecacheRoute”,因此系统已将其移除。
  • createMatchCalback() 方法已从 PrecacheController 中移除。您可以改用新的 PrecacheRoute
  • createHandler() 方法已从 PrecacheController 中移除。您可以改用 PrecacheController 对象的 strategy 属性来处理请求。
  • createHandler() 静态导出已从 workbox-precaching 模块中移除。作为替代,开发者应该构建一个 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() 的调用)而言是唯一的。这样一来,开发者便可以编写插件,让一个回调可以根据同一插件中另一个回调的行为有条件地执行某些操作(例如,计算运行 requestWillFetchfetchDidSucceedfetchDidFail 之间的时间增量)。

新增了插件生命周期回调

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

  • handlerWillStart:在任何处理程序逻辑开始运行之前调用。此回调可用于设置初始处理程序状态(例如,记录开始时间)。
  • handlerWillRespond:在策略 handle() 方法返回响应之前调用。此回调可用于修改该响应,然后再将其返回到路线处理程序或其他自定义逻辑。
  • handlerDidRespond:在策略的 handle() 方法返回响应后调用。此回调可用于记录任何最终响应详细信息,例如在其他插件进行更改之后。
  • handlerDidComplete:在通过此策略调用添加到事件的所有延长生命周期 Promise 处理完毕后调用。此回调可用于报告任何需要等待处理程序完成才能进行计算的数据(例如,缓存命中状态、缓存延迟、网络延迟)。
  • handlerDidError:在处理程序无法提供来自任何来源的有效响应时调用。此回调可用于提供“后备”内容来替代网络连接错误。

实现自己的自定义策略的开发者无需担心如何自行调用这些回调;这些回调全部由新的 Strategy 基类处理。

处理程序的 TypeScript 类型更准确

各种回调方法的 TypeScript 定义已标准化。这应该可以为使用 TypeScript 并编写自己的代码来实现或调用处理程序的开发者提供更好的体验。

工作框窗口

新的 messageSkipPause() 方法

workbox-window 模块中新增了一个方法 messageSkipWaiting(),用于简化告知“等待”的 Service Worker 激活过程的过程。这有一些改进:

  • 它使用实际的标准消息正文 {type: 'SKIP_WAITING'} 调用 postMessage(),Workbox 生成的 Service Worker 会检查该正文以触发 skipWaiting()
  • 它会选择正确的“等待”Service Worker 将此消息发布到它,即使它不是 workbox-window 注册时使用的 Service Worker。

移除了“external”事件,改为使用 isExternal 属性

移除了 workbox-window 中的所有 "external" 事件,以代替 isExternal 属性设置为 true 的“normal”事件。这样一来,那些关注这种差异的开发者仍然可以检测到该属性,而不需要知道这一点的开发者可以忽略该属性。

清理器“为用户提供页面重新加载”方案

得益于上述两项更改,“为用户重新加载网页”这一方案可以简化:

MULTI_LINE_CODE_PLACEHOLDER_0

工作框路由

系统会向 workbox-routing 中使用的 matchCallback 函数传递一个新的布尔值参数 sameOrigin。如果请求针对的是同源网址,则设置为 true,否则设置为 false。

这样可以简化一些常见的样板代码:

MULTI_LINE_CODE_PLACEHOLDER_1

workbox-expiration 中的 matchOptions

现在,您可以在 workbox-expiration 中设置 matchOptions,然后它会作为 CacheQueryOptions 传递给底层 cache.delete() 调用。(大多数开发者无需这样做)。

工作区预缓存

使用 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 为您创建 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 上提交问题告诉我们。