在 Workbox 中使用 skipWaiting 和 clientsClaim 有什么缺点? [英] What are the downsides to using skipWaiting and clientsClaim with Workbox?

查看:37
本文介绍了在 Workbox 中使用 skipWaiting 和 clientsClaim 有什么缺点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

作为一个相关问题,clientsClaim究竟控制什么?只需打开skipWaiting就可以解决上述问题;那么clientsClaim有什么作用呢?

解决方案

作为背景,我建议阅读服务工作者生命周期".它是从通用 Service Worker 的角度编写的,但这些要点也适用于基于 Workbox 的 Service Worker.

这些概念也从使用create-react-app的角度进行了更详细的解释,在这个懒加载时注意"谈话和微型网站.

Workbox 的实现

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

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

<块引用>

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

使用一些风险skipWaiting,为了安全起见,我们默认在 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 的所有打开客户端都已关闭.这通常是您想要的.

注意:虽然使用 Service Worker 可能更容易遇到此类问题,但对于延迟加载版本化 URL 的所有 Web 应用程序来说,这是一个问题.您应该始终进行错误处理以检测延迟加载失败并尝试通过例如强制重新加载页面来恢复.如果您拥有该恢复逻辑,并且您对该 UX 感到满意,那么您仍然可以选择启用 skipWaiting.

风险 2:延迟加载不兼容的逻辑

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

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

注意:和以前一样,这不是 Service Worker 独有的风险——任何动态加载未版本化 URL 的 Web 应用程序最终可能会在最近的部署后加载不兼容的逻辑.

<块引用>

那么clientsClaim 是做什么的?

clientsClaim 确保在服务工作者激活后,服务工作者将立即控制范围内的所有不受控制的客户端(即页面).如果你不启用它,那么直到下一次导航它们才会被控制.

启用通常比 skipWaiting 更安全,如果您希望 Service Worker 尽早开始填充运行时缓存,这会很有帮助.

我会向您介绍部分 在 Service Worker Lifecycle 文档中了解更多信息.

By default skipWaiting is set to false in Workbox. Assuming you're only using the Workbox-created service worker for caching, are there any downsides to setting this to true? Without doing so, the next build of your app will ship updated resource urls (from webpack). These urls will be updated in the service worker's precache manifest, but without skipWaiting, the updated service worker will not be activated to take advantage of them, until the user closes their browser and re-opens.

These updated resources will be loaded correctly (webpack will load the resources with the new hash values in them), but they'll never be cached until, again, the user closes all open browsers running the service worker, and re-opens. Under these circumstances, is there any reason to not just set skipWaiting to true?

As a related issue, what exactly does clientsClaim control? The above problem is fixed by merely switching skipWaiting on; so what does clientsClaim do?

解决方案

As background, I'd recommend reading "The Service Worker Lifecycle". It's written from the generic service worker perspective, but the points apply to Workbox-powered service workers as well.

These concepts are also explained in more detail, from the perspective of using create-react-app, in this "Paying Attention while Loading Lazily" talk and microsite.

Workbox's implementation

Workbox uses an install event handler to cache new or updated entries in the precache manifest (appending a __WB_REVISION__ query param to the entries' URLs when needed, to avoid overwriting existing entries with different revisions), and it uses the activate event handler to delete previously cached entries that are no longer listed in the precache manifest.

If skipWaiting is true, then activate handler, which is responsible for cleaning up outdated URLs from the cache, would be executed immediately after an updated service worker is installed.

Under these circumstances, is there any reason to not just set skipWaiting to true?

There are a few risks to using skipWaiting, and to err on the side of safety, we disable it by default in Workbox. (It was enabled by default in older, sw-precache-generated service workers.)

Let's assume a scenario in which your HTML is loaded cache-first (generally a best practice), and then sometime after that load, a service worker update is detected.

Risk 1: Lazy-loading of fingerprinted content

Modern web apps often combine two techniques: asynchronous lazy-loading of resources only when needed (e.g. switching to a new view in a single page app) and adding fingerprints (hashes) to uniquely identify URLs based on the content they contain.

Traditionally, it's either the HTML itself (or some JavaScript that contains route information which is also loaded early on in the page lifecycle) that contains a reference to the current list of URLs that need to be lazy-loaded.

Let's say that the version of your web app which was initially loaded (before the service worker update happened) thinks that the URL /view-one.abcd1234.js needs to be loaded in order to render /view-one. But in the meantime, you've deployed an update to your code, and /view-one.abcd1234.js has been replaced on your server and in your precache manifest by /view-one.7890abcd.js.

If skipWaiting is true, then /view-one.abcd1234.js will be purged from the caches as part of the activate event. Chances are that you've already purged it from your server as part of your deployment as well. So that request will fail.

If skipWaiting is false, then /view-one.abcd1234.js will continue to be available in your caches until all the open clients of the service worker have been closed. That's usually what you'd want.

Note: While using a service worker can make it more likely to run into this class of problem, it's an issue for all web apps that lazy-load versioned URLs. You should always have error handling in place to detect lazy-loading failures and attempt to recover by, e.g., forcibly reloading your page. If you have that recovery logic in place, and you're okay with that UX, you might choose to enable skipWaiting anyway.

Risk 2: Lazy-loading of incompatible logic

This is similar to the first risk, but it applies when you don't have hash fingerprints in your URLs. If you deploy an update to your HTML and a corresponding update to one of your views, existing clients can end lazy-loading a version of /view-one.js that doesn't correspond to the structure of the HTML that was fetched from the cache.

If skipWaiting is false, then this isn't likely to happen, since the /view-one.js that's loaded from the cache should correspond to the HTML structure that was loaded from the same cache. That's why it's a safer default.

Note: Like before, this isn't a risk that's unique to service workers—any web app that dynamically loads unversioned URLs might end up loading incompatible logic following a recent deployment.

so what does clientsClaim do?

clientsClaim ensures that all uncontrolled clients (i.e. pages) that are within scope will be controlled by a service worker immediately after that service worker activates. If you don't enable it, then they won't be controlled until the next navigation.

It's usually safer to enable than skipWaiting, and can be helpful if you want the service worker to start populating runtime caches sooner rather than later.

I'll refer you to the section in the Service Worker Lifecycle doc for more info.

这篇关于在 Workbox 中使用 skipWaiting 和 clientsClaim 有什么缺点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆