首页 > 解决方案 > 将 skipWaiting 和 clientsClaim 与 Workbox 一起使用有什么缺点?

问题描述

默认情况下skipWaiting在 Workbox 中设置为 false。假设您使用 Workbox 创建的服务工作者进行缓存,将其设置为 true 有什么缺点吗?如果不这样做,您的应用程序的下一个构建将发布更新的资源 url(来自 webpack)。这些 url 将在 service worker 的预缓存清单中更新,但如果没有skipWaiting,更新后的 service worker 将不会被激活以利用它们,直到用户关闭浏览器并重新打开。

这些更新的资源被正确加载(webpack 将加载具有新哈希值的资源),但它们永远不会被缓存,直到用户再次关闭所有运行服务工作者的打开浏览器并重新打开。在这种情况下,有什么理由不只是设置skipWaiting为 true 吗?

作为一个相关问题,究竟clientsClaim控制什么?只需打开 skipWaiting 即可解决上述问题;那么clientsClaim是做什么的呢?

标签: service-workerworkbox

解决方案


作为背景,我建议阅读“服务工作者生命周期”。它是从通用服务工作者的角度编写的,但这些要点也适用于 Workbox 支持的服务工作者。

这些概念也有更详细的解释,从使用的角度来看create-react-app,在这个“在加载懒惰的同时注意”谈话和微站。

Workbox 的实现

Workbox 使用install事件处理程序在预缓存清单中缓存新的或更新的条目(__WB_REVISION__在需要时将查询参数附加到条目的 URL,以避免用不同的修订覆盖现有条目),并使用activate事件处理程序删除以前缓存的条目不再在预缓存清单中列出。

如果skipWaiting为真,则activate负责从缓存中清理过时 URL 的处理程序将在安装更新的 service worker 后立即执行。

在这种情况下,有什么理由不只是设置skipWaiting为 true 吗?

使用有一些风险skipWaiting,为了安全起见,我们在 Workbox 中默认禁用它。(默认情况下,它在较旧的、sw-precache生成的服务工作者中启用。)

让我们假设您的 HTML 是先缓存加载的(通常是最佳实践),然后在加载后的某个时间,检测到服务工作线程更新。

风险 1:延迟加载指纹内容

现代 Web 应用程序通常结合两种技术:仅在需要时异步延迟加载资源(例如切换到单页应用程序中的新视图)和添加指纹(哈希)以根据 URL 包含的内容唯一标识 URL。

传统上,它要么是 HTML 本身(或一些包含在页面生命周期早期加载的路由信息​​的 JavaScript),它包含对需要延迟加载的当前 URL 列表的引用。

假设最初加载的 Web 应用程序版本(在 service worker 更新发生之前)认为/view-one.abcd1234.js需要加载 URL 才能呈现/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:不兼容逻辑的延迟加载

这类似于第一个风险,但它适用于您的 URL 中没有哈希指纹的情况。如果您将更新部署到您的 HTML 并为您的一个视图部署相应更新,则现有客户端可以结束延迟加载/view-one.js与从缓存中获取的 HTML 结构不对应的版本。

如果skipWaiting为 false,那么这不太可能发生,因为/view-one.js从缓存中加载的 应该对应于从同一缓存中加载的 HTML 结构。这就是为什么它是一个更安全的默认值。

注意:和以前一样,这不是服务工作者独有的风险——任何动态加载未版本化 URL 的 Web 应用程序最终都可能在最近的部署之后加载不兼容的逻辑。

那么clientsClaim是做什么的呢?

clientsClaim确保范围内的所有不受控制的客户端(即页面)将在服务工作人员激活后立即由服务工作人员控制。如果您不启用它,那么它们将在下一次导航之前不受控制。

启用它通常比 更安全skipWaiting,并且如果您希望服务工作者尽快开始填充运行时缓存而不是稍后,它会很有帮助。

我将向您推荐 Service Worker 生命周期文档中的部分以获取更多信息。


推荐阅读