我想在这里扩展一些其他答案,并从“在将服务工作者投入生产时如何确保可以进行任何必要更改的策略”角度来看待这个问题。这些更改可能包括在生产中发现的修复任何小错误,或者(但希望不会出现)由于无法克服的错误而使服务工作者失效-所谓的“紧急停止开关”。
为了回答这个问题,假设您称之为
navigator.serviceWorker.register('service-worker.js')
在您的页面中,意味着您的服务工作者 JavaScript 资源是 service-worker.js
。(如果您不确定使用了确切的服务工作者 URL —— 也许是因为您向服务工作者脚本添加了哈希或版本信息,请参见下面的内容。)
问题归结为如何解决service-worker.js
代码中的初始问题。如果只是一个小的 bug 修复,那么您显然可以直接进行更改并重新部署service-worker.js
到您的托管环境中。如果没有明显的 bug 修复,并且您不想让您的用户在您花费时间解决问题时继续运行有问题的服务工作者代码,保留一个简单的、无操作 (no-op) 的service-worker.js
是个好主意,就像以下这样:
self.addEventListener('install', () => {
self.skipWaiting();
});
这应该是您的空操作service-worker.js
文件所需的全部内容。因为没有注册fetch
处理程序,所有从受控页面发起的导航和资源请求将直接针对网络进行,实际上使您获得了与无服务工作者完全相同的行为。
其他步骤
可能还可以更进一步,强制删除使用Cache Storage API存储的所有内容,或者显式注销服务工作者。 对于大多数常见情况,这可能过度,遵循上述建议应该足以使您的当前用户获得预期的行为,并且一旦修复错误就可以重新部署更新。启动即使是无操作服务工作者也存在某种程度的开销,因此如果没有计划重新部署有意义的服务工作者代码,您可以选择注销服务工作者路线。
如果您已经处于服务HTTP缓存指令提供给它的生命周期比您的用户等待的时间长的service-worker.js
的情况下,请记住,在桌面浏览器上,Shift + Reload会强制页面在服务工作者控制外重新加载。不是每个用户都知道如何做到这一点,在移动设备上也不可能。因此,不要依赖Shift + Reload作为可行的回滚计划。
如果您不知道服务工作者网址怎么办?
上述信息假设您知道服务工作者URL是什么- service-worker.js
,sw.js
或其他某些基本不变的东西。但是,如果您在服务工作者脚本中包含了某种版本或哈希信息,例如service-worker.abcd1234.js
怎么办?
首先,请尽量避免这种情况-这是最佳做法违反。但是,如果您已经部署了许多版本化的服务工作者URL,并且需要禁用所有用户,而不管他们注册了哪个URL,则有一种方法可以解决问题。
每次浏览器请求服务工作者脚本时,无论是初始注册还是更新检查,它都会设置一个名为Service-Worker:
的HTTP请求头。
假设您对后端HTTP服务器具有完全控制权,您可以检查传入请求是否存在此Service-Worker:
头,并始终响应您的无操作服务工作者脚本响应,而不管请求URL是什么。
配置Web服务器以执行此操作的详细信息将因服务器而异。
Clear-Site-Data响应头
最后一点:当特定的HTTP响应头作为任何响应的一部分返回时,某些浏览器将自动清除特定数据并可能取消注册服务工作者:Clear-Site-Data:
。
设置此标题可在尝试从错误的服务工作者部署中恢复时提供帮助,并且停止开关场景包括在该功能的规范中作为示例用例。
在仅使用其作为停止开关之前,请检查Clear-Site-Data:
的浏览器支持情况。截至2019年7月,它不被100%支持服务工作者的浏览器支持,因此,如果您担心在所有浏览器中从故障服务工作者中恢复,最安全的方法是与上述技术一起使用Clear-Site-Data:
。