如何删除有缺陷的服务工作者,或实施"kill switch"?

Paq*_*oft 46 javascript service-worker

我正在玩我的计算机中的服务工作者API,所以我可以掌握如何在我的真实应用程序中从中受益.

我遇到了一个奇怪的情况,我注册了一个拦截fetch事件的服务工作者,因此它可以在向源发送请求之前检查其缓存中是否有所请求的内容.问题是这段代码有一个错误,导致函数无法发出请求,因此我的页面留空; 什么都没发生.由于服务工作者已经注册,第二次加载页面时它会拦截第一个请求(加载HTML的请求).因为我有这个错误,那个fetch事件失败了,它从不会请求HTML,所有我都看到它是一个空白页面.

在这种情况下,我知道删除坏服务工作者脚本的唯一方法是通过chrome://serviceworker-internals/控制台.如果此错误进入实时网站,这是解决它的最佳方法吗?

谢谢!

Jef*_*ick 73

我想在这里扩展一些其他答案,并从"在将服务工作者推广到生产时可以使用哪些策略以确保我可以进行任何必要的更改"的角度来处理这个问题?这些更改可能包括修复您在生产中发现的任何小错误,或者它可能(但希望不会)包括由于不可克服的错误而中和服务工作者 - 即所谓的"终止开关".

出于这个答案的目的,让我们假设你打电话

navigator.serviceWorker.register('service-worker.js');
Run Code Online (Sandbox Code Playgroud)

在您的页面上,这意味着您的服务工作者JavaScript资源是service-worker.js.

我的第一条建议是阅读标准HTTP缓存如何影响服务工作者的JavaScript保持最新的方式.关于此问题,有大量的错误信息,我希望这个Stack Overflow的答案可以清除其中一些,并解释服务工作者检查更新的方式和时间.要总结那些没有点击其他答案的人,在确定是否请求服务工作者JavaScript的新副本或使用缓存副本时,您的浏览器将遵循HTTP缓存指令,最长可达1天. .因此,如果您希望能够灵活地快速推出新的服务工作者JavaScript来修复错误,请service-worker.js使用HTTP缓存指令为其提供短期或0最大年龄. 更新:截至2018年6月,默认情况下,所有常绿浏览器在检查服务工作者更新时都会忽略service-worker.js标头.

一旦为您service-worker.js提供了适当的HTTP缓存指令,问题归结为您如何解决service-worker.js代码中的初始问题.如果这是一个小错误修复,那么您显然可以进行更改并重新部署fetch到您的托管环境.如果没有明显的错误修复,并且您不想让您的用户在花费时间来制定解决方案时运行错误的服务工作者代码,那么保持一个简单的,无操作的 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);
    });
  });
});
*/
Run Code Online (Sandbox Code Playgroud)

那应该是你所有的无操作service-worker.js需要包含的.由于没有sw.js注册处理程序,来自受控页面的所有导航和资源请求最终将直接针对网络,有效地为您提供了相同的行为,如果根本没有服务工作者的话.

可以更进一步,强制删除使用Cache Storage API存储的所有内容,或者完全取消注册服务工作者.对于大多数常见情况,这可能会过度,并且遵循上述建议应足以让您处于当前用户获得预期行为的状态,并且您已准备好在修复错误后重新部署更新.启动即使是无操作的服务工作者也会有一定程度的开销,因此如果您没有计划重新部署有意义的服务工作者代码,则可以选择取消注册服务工作者的路径.

如果您已经处于service-worker.abcd1234.js使用HTTP缓存指令的情况下,它的生命周期比用户可以等待的时间长,请记住桌面浏览器上的Shift + Reload将强制页面重新加载服务人员控制.并非每个用户都知道如何做到这一点,但这在移动设备上是不可能的.因此,不要依赖Shift + Reload作为可行的回滚计划.


Fra*_*ano 8

这是一个非常糟糕的情况,希望在生产中不会发生在你身上.

在这种情况下,如果您不想浏览不同浏览器的开发工具,chrome://serviceworker-internals/基于blink的浏览器,或者about:serviceworkers(about:debugging#workers在将来)Firefox中,我会想到两件事:

  1. 使用serviceworker更新机制.您的用户代理将检查注册的工作人员是否有任何更改,将获取它并将activate再次进入阶段.因此,您可以更改serviceworker脚本,修复(清除缓存等)任何奇怪的情况并继续工作.唯一的缺点是你需要等到浏览器更新可能为1天的工作人员.
  2. 添加某种杀戮开关给你的工人.有一个特殊的URL,您可以指向用户访问,可以恢复您的缓存的状态等.

我不确定清除浏览器数据是否会删除工作人员,因此这可能是另一种选择.


Pra*_*han 6

您可以使用javascript"取消注册"服务工作者.这是一个例子:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.getRegistrations().then(function (registrations) {
    //returns installed service workers
    if (registrations.length) {
      for(let registration of registrations) {
        registration.unregister();
      }
    }
  });
}
Run Code Online (Sandbox Code Playgroud)