如何强制服务工作者更新?

时间:2017-01-27 21:14:15

标签: html5 service-worker offline-caching progressive-web-apps sw-precache

我使用sw-precache通过Polymer CLI构建过程生成我的服务工作,因此它打算更新更新文件的哈希,以表示需要更新缓存。但是我的更新内容没有在缓存中被替换,所以如果我用ctrl + r刷新它会得到一个旧版本但是如果我用ctrl + shift + r刷新则会得到新版本。原因可能是我的服务人员没有更新。

This doc表示

  

如果服务工作文件中甚至存在字节差异   与目前的情况相比,它认为是新的。

,但如果我的新服务工作者没有更改字节怎么办? (如果只有一个哈希发生了变化就会发生)。如何配置sw-precache以在每次新请求时更新服务工作?

6 个答案:

答案 0 :(得分:9)

如果一个文件的哈希值发生了变化,那么这足以确保sw-precache生成的服务工作者JavaScript文件发生变化。反过来,这足以触发服务工作者更新流程。

如果您在测试时没有看到更新流程被触发,那么可能是由于服务工作者JavaScript文件通过HTTP缓存标头提供,导致从浏览器中获取它缓存而不是来自网络。

有关HTTP缓存标头如何发挥作用的讨论,请参阅https://stackoverflow.com/a/38854905/385997

答案 1 :(得分:8)

正如之前的答案所述,浏览器有一天(24小时)的内置限制来查找服务工作者的更新,但您需要注意的是,您仍然需要调用{{1在.update()对象上,否则将使用该文件的原始版本。

在测试Chrome中的更改时,我总是右键单击刷新按钮并选择“清空缓存和硬重置”。 (在开发人员工具打开时可以使用选项)在处理我的服务工作者脚本时。

答案 2 :(得分:8)

'sw-precache'已被Workbox取代,它为您要预先缓存的文件生成哈希值,并将这些哈希值添加到服务工作者的源代码中(我不知道sw-precache以同样的方式工作,杰夫的回答表明它确实如此)。如果您要预先缓存的任何文件发生更改 - 并且您重新运行构建 - 更新了服务工作者中更新的哈希值,这几乎可以保证服务工作者“至少有一个字节不同”。

当您重新加载(ctrl-r)或重新访问您的应用时,浏览器将再次获取为其注册的服务工作者。而且,如果该服务工作者已经更改,它将“排队”以管理该应用程序。但是,在关闭打开应用程序的所有选项卡,然后打开一个新应用程序之前,它不会开始管理应用程序。

当你硬刷新(shift-ctrl-rit’ll always load without a controller时,这与使用新服务工作者不同。

为了在开发期间进行测试,我在devtools中使用skip waiting来使新服务工作者替换旧服务工作者,而无需等待我关闭所有选项卡。

答案 3 :(得分:1)

从UX的角度来看,我已经实现的一个选项是在服务工作者上调用unregister方法。 (https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/unregister

注销过程完成后,您可以:

  1. 强制窗口刷新(window.location.reload)
  2. 根据您的加载过程,您可以获取新的服务工作程序,该服务工作程序有望缓存所有新内容。

我之前在服务工作者中遇到过奇怪的问题,因此这种类型的解决方案使您可以在不强制用户清除其实际浏览器高速缓存的同时,稍微清除旧高速缓存并刷新应用程序的状态。重新加载您的应用程序。

EX(如何注销):

serviceworker.unregister()
    .then( unregResult => { 
       //You can check if successful with Promise result 'unregResult'
       window.location.reload();
    })

答案 4 :(得分:0)

service‑worker.js 中存储版本号

控制 service-worker.js 中的单个字符更改将自动触发 PWA 更新。因此,如果您将版本号存储在此文件的 const 中并对其进行更改,则会触发 PWA 的更新。

最终如何处理更新由 service-worker.js 决定。可以根据 PWA 资产的大小和波动性定义不同的更新策略。

但是,有一个重要警告。请确保您的资产服务器上的 .htaccess 文件设置的浏览器缓存到期指令设置为持续时间非常短(例如hours)甚至到none。 如果不这样做,将导致浏览器在 manifest.jsonservice-worker.js 中的未来几天都看不到任何变化。

有关 Service Worker 行为的更多详细信息,请访问 Google Web Fundamentals

答案 5 :(得分:-2)

const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {

    //Force the Service Worker to Upddate
    self.registration.update();

    const notification = JSON.parse(payload.data.notification);
    return self.registration.showNotification(notification.title, notification);

});