作为背景,我建议阅读“The Service Worker Lifecycle”。它是从通用 Service Worker 的角度编写的,但这些要点也适用于 Workbox 支持的 Service Worker。
在这个“Paying Attention while Loading Lazily”谈话和微站中,也从使用create-react-app的角度更详细地解释了这些概念。
Workbox 的实现
Workbox 使用 install 事件处理程序在预缓存清单中缓存新的或更新的条目(在需要时将 __WB_REVISION__ 查询参数附加到条目的 URL,以避免用不同的修订覆盖现有条目),它使用activate 事件处理程序,用于删除以前缓存的条目,这些条目不再列在预缓存清单中。
如果skipWaiting 为真,则activate 处理程序负责从缓存中清理过时的URL,将在安装更新的服务工作者后立即执行。
在这种情况下,是否有理由不将skipWaiting 设置为true?
使用skipWaiting 有一个few risks,为了安全起见,我们在Workbox 中默认禁用它。 (它在较早的 sw-precache 生成的服务工作者中默认启用。)
假设您的 HTML 是先缓存加载的(通常是最佳实践),然后在加载后的某个时间检测到 Service Worker 更新。
风险 1:延迟加载指纹内容
现代网络应用程序通常结合两种技术:仅在需要时异步延迟加载资源(例如,在单页应用程序中切换到新视图)和添加指纹(哈希)以根据 URL 包含的内容唯一标识 URL。
传统上,要么是 HTML 本身(或一些包含在页面生命周期早期加载的路由信息的 JavaScript)包含对需要延迟加载的当前 URL 列表的引用。
假设最初加载的 Web 应用程序版本(在 Service Worker 更新发生之前)认为需要加载 URL /view-one.abcd1234.js 才能呈现 /view-one。但与此同时,您已经部署了代码更新,并且在您的服务器和预缓存清单中,/view-one.abcd1234.js 已被 /view-one.7890abcd.js 替换。
如果skipWaiting 为真,那么/view-one.abcd1234.js 将作为activate 事件的一部分从缓存中清除。作为部署的一部分,您可能已经从服务器中清除了它。所以这个请求会失败。
如果 skipWaiting 为 false,则 /view-one.abcd1234.js 将继续在您的缓存中可用,直到服务工作者的所有打开的客户端都已关闭。这通常是您想要的。
注意:虽然使用 service worker 可能会使其更容易遇到此类问题,但对于所有延迟加载版本化 URL 的 Web 应用程序来说,这是一个问题。您应该始终进行错误处理以检测延迟加载失败并尝试通过例如强制重新加载页面来恢复。如果你有那个恢复逻辑,并且你对那个 UX 没问题,你可以选择启用skipWaiting。
风险 2:不兼容逻辑的延迟加载
这与第一个风险相似,但它适用于您的网址中没有哈希指纹的情况。如果您为 HTML 部署更新并为您的一个视图部署相应更新,则现有客户端可以结束延迟加载与从缓存中获取的 HTML 结构不对应的/view-one.js 版本。
如果skipWaiting 为假,那么这不太可能发生,因为从缓存加载的/view-one.js 应该对应于从同一个缓存加载的HTML 结构。这就是为什么它是一个更安全的默认设置。
注意:和以前一样,这不是服务工作者独有的风险——任何动态加载未版本化 URL 的 Web 应用程序最终都可能在最近的部署之后加载不兼容的逻辑。
那么clientsClaim是做什么的呢?
clientsClaim 确保范围内的所有不受控制的客户端(即页面)在服务工作人员激活后立即由服务工作人员控制。如果您不启用它,那么直到下一次导航才会对其进行控制。
启用它通常比skipWaiting 更安全,如果您希望服务工作者尽快开始填充运行时缓存,这会很有帮助。
我会将您推荐给 Service Worker 生命周期文档中的 section 以获取更多信息。