如何使用新部署的站点版本 (Firebase) 从用户的浏览器中删除先前部署中注册的服务工作者?

How to remove a service worker registered in previous deploy from users' browsers with the newly deployed version of site (Firebase)?

我已经通过现有项目将网站的新版本(它在 Polymer 上,现在在 Vue.js 上)部署到 Firebase。

我在新项目中使用带有 Webpack (vue init webpack my-project) 的默认 Vue.js 模板


现在我已经部署了新版本,当我打开网站时,我只看到一个缓存 shell,我认为这是 service worker 的错

为了从 Firebase 获取实际的当前文件,我(以及所有以前的访问者)现在每次都必须硬刷新网站(Ctrl+F5 在 firefox 中)

控制台

现在,在浏览器控制台(网络选项卡)中我看到:


我已将此代码添加到 firebase.json,然后 npm run build 试图删除服务工作者,但问题仍然存在

Firebase.json

{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "headers": [
      { "source":"/service-worker.js", "headers": [{"key": "Cache-Control", "value": "no-cache"}] }
    ]
  }
}

上一个项目的 Service worker 代码

我没有在新部署的版本上使用任何服务工作者。但是之前的deploy注册了一个service worker

我使用的是 Polymer 1.0 框架库中的默认 sw-precache 组件,该库内置于我使用的 pre-configured Polymer 入门工具包模板中。 Service Worker 是在构建时生成的

捆绑 > service-worker.js: https://jsfiddle.net/uydjzw13/

未捆绑 > service-worker.js: https://jsfiddle.net/t42fdgow/


问题:

有没有办法从所有站点访问者的浏览器中删除那个旧的服务工作者,以便他们始终获得新部署的版本?也许我可以用 Webpack 或 Firebase 以某种方式做到这一点?


如果我只是从 Firebase 中删除之前使用 service worker 部署的版本,它会得到修复吗?

或者我可以部署另一个版本的 service worker,它的唯一功能是删除所有以前的缓存并取消注册以前的 service worker,如果可能的话?

或者我可以使用这样的东西吗?: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/unregister

我不确定如何正确地做到这一点,并且不会不小心注册更多我也无法摆脱的服务工作者。

我认为这取决于你的 service worker 在做什么以及它是如何做的。这个item from Google talks about the difficulties relating to service workers that cache code, and they recommend using this library

什么是 Service Worker?

Service Worker 位于客户端和服务器之间,驻留在用户浏览器中。他们有多种角色,可以执行许多任务。其中一项任务是从网站缓存 script/code(它是 shell)。

历史对比

在许多方面,缓存代码看起来就像 1990 年代后期互联网的运作方式。那时你可以进入文件夹的浏览器历史并打开文件夹并获得部分工作的网站,即使在离线时也是如此。

有风险

Service Worker 可以执行与查看存储在计算机上的网站文件夹相同的任务,通过在回调到服务器获取文件之前执行此操作,您的网站看起来和感觉起来都超级快,因为 Service Worker 在本地交付了您网站的存储版本。

但是,存在着巨大的风险。如果在用户访问 url 时未正确设置 service worker,则 service worker 将始终首先指向网站的缓存版本。这意味着无论您更改或交付什么代码,客户都不会真正要求它。

这是最糟糕的情况,因为解决此问题的唯一方法是让用户进入开发人员面板并删除 service worker,或清除浏览器数据,但他们可能永远不知道该怎么做,而只是相信一个网站坏了。

我终于找到了解决办法!

所以如果你有同样的问题,就这样做:

1 安装 this webpack 插件(如果您在项目中使用 webpack)

npm install webpack-remove-serviceworker-plugin

2 在 webpack.prod.conf.js 文件中创建常量(或任何您的生产配置调用)

const RemoveServiceWorkerPlugin = require('webpack-remove-serviceworker-plugin')

3 将插件添加到 plugins: [ ] 文件中(如果您的项目中不使用它们,请不要将 ; 放在那里):

new RemoveServiceWorkerPlugin({ filename: 'service-worker.js' });

4 将 service-worker.js 文件名更改为您之前调用的任何服务工作者(您需要删除的那个。您可以在网络中找到它的名称加载页面时的开发人员工具选项卡)

5 再次构建项目并部署


如果你不使用 webpack,你可以尝试做 this - 将旧的 service worker 替换为一个可以自行注销的 service worker:

registration.unregister().then(async () => {
  // optionally, get controlled pages to refresh:
  for (const client of await clients.matchAll()) {
    client.navigate(client.url);
  }
});

看看这个合并后的 Pull Request 它实现了标志 --skip-plugins ,您可以在其中指定要在 npm run build 期间忽略的插件的名称或类似的东西.关闭 PWA 插件似乎是个好主意。