我想扩展这里的其他一些答案,并从“在将 Service Worker 部署到生产环境时可以使用哪些策略来确保我可以进行任何需要的更改”的角度来解决这个问题?这些更改可能包括修复您在生产中发现的任何小错误,或者可能(但希望不会)包括由于无法克服的错误(即所谓的“终止开关”)而使 Service Worker 失效。
出于此答案的目的,假设您致电
navigator.serviceWorker.register('service-worker.js');
在您的页面上,这意味着您的 Service Worker JavaScript 资源是service-worker.js
. (如果您不确定所使用的确切 Service Worker URL,请参见下文——可能是因为您向 Service Worker 脚本添加了哈希或版本信息。)
问题归结为如何解决service-worker.js
代码中的初始问题。如果这是一个小错误修复,那么您显然可以进行更改并将其重新部署service-worker.js
到您的托管环境。如果没有明显的bug修复和你不想离开你的用户运行马车服务人员的代码,而你花时间来制定出一个解决方案,这是一个好主意,让一个简单的,无操作 service-worker.js
得心应手,就像下列的:
// A simple, no-op service worker that takes immediate control.
self.addEventListener('install', () => {
// Skip over the "waiting" lifecycle state, to ensure that our
// new service worker is activated immediately, even if there's
// another tab open controlled by our older service worker code.
self.skipWaiting();
});
/*
self.addEventListener('activate', () => {
// Optional: Get a list of all the current open windows/tabs under
// our service worker's control, and force them to reload.
// This can "unbreak" any open windows/tabs as soon as the new
// service worker activates, rather than users having to manually reload.
self.clients.matchAll({type: 'window'}).then(windowClients => {
windowClients.forEach(windowClient => {
windowClient.navigate(windowClient.url);
});
});
});
*/
这应该是您的无操作service-worker.js
需要包含的所有内容。因为没有fetch
注册处理程序,来自受控页面的所有导航和资源请求最终将直接针对网络,有效地为您提供与根本没有 Service Worker 时相同的行为。
附加步骤
可以更进一步,强行删除使用Cache Storage API存储的所有内容,或者明确地完全取消注册 Service Worker。对于大多数常见情况,这可能会有点矫枉过正,遵循上述建议应该足以让您处于当前用户获得预期行为的状态,并且一旦您修复了错误,您就可以重新部署更新. 即使是启动一个无操作的 Service Worker 也有一定程度的开销,所以如果你没有计划重新部署有意义的 Service Worker 代码,你可以走取消注册 Service Worker的路线。
如果您已经在service-worker.js
使用 HTTP 缓存指令为其提供服务的情况下,它的生命周期比您的用户可以等待的时间长,请记住,桌面浏览器上的Shift + Reload将强制页面在外部重新加载服务工作者控制。并非每个用户都知道如何执行此操作,但在移动设备上也不可能。所以不要依赖 Shift + Reload 作为可行的回滚计划。
如果您不知道 Service Worker URL 怎么办?
上面的信息假定你知道什么服务工作者URL是- service-worker.js
,sw.js
或别的东西的有效不变。但是,如果您在 Service Worker 脚本中包含某种版本控制或哈希信息,例如service-worker.abcd1234.js
?
首先,在未来尽量避免这种情况——这是违反最佳实践的。但是,如果您已经部署了许多版本化的 Service Worker URL,并且您需要为所有用户禁用某些功能,无论他们注册了哪个 URL,都有一个出路。
每次浏览器向 Service Worker 脚本发出请求时,无论是初始注册还是更新检查,它都会设置一个名为Service-Worker:
.
假设您可以完全控制后端 HTTP 服务器,您可以检查传入请求是否存在此Service-Worker:
标头,并始终以您的无操作服务工作者脚本响应进行响应,无论请求 URL 是什么。
配置您的 Web 服务器以执行此操作的具体细节因服务器而异。
Clear-Site-Data: 响应头
最后一点:当特殊的 HTTP 响应标头作为任何响应的一部分返回时,某些浏览器会自动清除特定数据并可能取消注册服务工作者:Clear-Site-Data:
。
尝试从错误的 Service Worker 部署中恢复时,设置此标头会很有帮助,并且功能规范中包含终止开关场景作为示例用例。
检查是很重要的浏览器支持的故事为Clear-Site-Data:
之前你依靠纯粹它作为一个杀死开关。截至 2019 年 7 月,支持 Service Worker 的浏览器并非 100% 都支持它,因此目前,Clear-Site-Data:
如果您担心在所有浏览器中从有故障的 Service Worker 中恢复,与上述技术一起使用是最安全的。