繁体   English   中英

尽管sw.js没有改变,Service Worker正在“安装”每个页面重新加载

[英]Service Worker is “installing” with every page reload though the sw.js did not change

我正在使用服务工作者来缓存Web应用程序的JS和CSS文件。 我主要使用谷歌Chrome示例中的代码,我唯一添加的是通知和倒计时,当“新的或更新的内容可用时”刷新窗口。

Google示例: https//github.com/GoogleChrome/sw-precache/blob/5699e5d049235ef0f668e8e2aa3bf2646ba3872f/demo/app/js/service-worker-registration.js

然而,这种情况经常发生,我不明白为什么。 肯定没有对服务器上的文件进行任何更改,但有时我仍然看到通知和窗口重新加载。

我预计只有当服务工作者管理的任何文件实际发生变化时才会发生这种情况(它们都是通过Webpack进行散列并且两者之间肯定没有变化)。

这是我使用的代码,在index.html内联:

/* eslint-env browser */
'use strict';
function reloadApp(delay) {
  var t = delay || 0;
  var message = 'New or updated content is available. Reloading app in {s} seconds';
  var getMessage = function() { return message.replace('{s}', t) }
  var div = document.createElement('div');
  div.id = 'update-notification';
  div.innerHTML = getMessage();
  document.body.appendChild(div);
  var intervalID = setInterval(function() {
    t = t - 1;
    if (t <= 0) {
      clearInterval(intervalID);
      window.location.reload();
    }
    else {
      div.innerHTML = getMessage();
    }
  }, 1000);
}
if ('serviceWorker' in navigator && window.location.protocol === 'https:') {
  navigator.serviceWorker.register('/service-worker.js').then(function(reg) {
    console.info('serviceWorker registered');
    reg.onupdatefound = function() {
      var installingWorker = reg.installing;
      installingWorker.onstatechange = function() {
        switch (installingWorker.state) {
          case 'installed':
            if (navigator.serviceWorker.controller) {
              reloadApp(5);
            } else {
              console.log('Content is now available offline!');
            }
            break;

          case 'redundant':
            console.error('The installing service worker became redundant.');
            break;
        }
      };
    };
  }).catch(function(e) {
    console.error('Error during service worker registration:', e);
  });
}

这是我做的改变:

switch (installingWorker.state) {
  case 'installed':
    if (navigator.serviceWorker.controller) {
      // At this point, the old content will have been purged and the fresh content will
      // have been added to the cache.
      // It's the perfect time to display a "New content is available; please refresh."
      // message in the page's interface.
      console.log('New or updated content is available.');
    } else {

成为:

switch (installingWorker.state) {
  case 'installed':
    if (navigator.serviceWorker.controller) {
      reloadApp(5);

服务工作者本身是通过sw-precache-webpack-plugin ,散列文件如下所示:

var precacheConfig = [["cms.CrudFactory.144344a2.js","6a65526f764f3caa4b8c6e0b84c1b31b"],["cms.routes.c20796b4.js","f8018476ceffa8b8f6ec00b297a6492d"],["common.cms-main.0f2db9ff.js","92017e838aff992e9f47f721cb07b6f0"],["common.licensing-main.8000b17d.js","0d43abd063567d5edaccdcf9c0e4c362"],["common.mediaplayer-main.314be5d2.js","2061501465a56e82d968d7998b9ac364"],["common.ordering-main.783e8605.js","0531c4a90a0fa9ea63fbe1f82e86f8c6"],["common.shared-main.0224b0ea.js","956ae4d2ddbddb09fb51804c09c83b22"],["common.stores-main.98246b60.js","cbdc46bc3abeac89f37e8f64b1737a22"],["component.App.284fec19.js","07f1923f1a0098bf9eba28fc7b307c18"],["component.AppToolbar.00e371de.js","9b542d4a85bdeece9d36ee4e389f6206"],["component.DevToolbar.652bf856.js","1744126e32774a93796146ac878ddd8e"],["component.Grid.4b964e52.js","755819ca2c7f911805e372401d638351"],["component.MediaPlayer.54db6e85.js","d0d8ae269665e810d1b997b473005f76"],["component.Search.05476f89.js","0cae8928aff533a6726dfaeb0661456a"],["data.country-list.d54f29a7.js","e27746418e02f75593a93b958a60807e"],["dev.sendSlackMessage.da8e22f4.js","ccb10829f18a727b79a5e8631bc4b2a2"],["index.html","02ff43eabc33c600e98785cffe7597d9"],["lib.gemini-scrollbar.df2fbf63.js","3941036bacb4a1432d22151ea7da073b"],["lib.isotope-horizontal.1604d974.js","6ac56d4296468c4428b5b5301a65938a"],["lib.isotope-packery.fabb73c3.js","808061641596e4b0ea2158b42d65915a"],["lib.react-color.265a6de0.js","f23f63d7e6934e381ffdc0405ecb449a"],["lib.react-date-picker.0a81fec3.js","778d1626645e439ad01e182ee589971a"],["lib.react-select.c768cf77.js","c8782991a161790ef2c9a2c7677da313"],["main.43e29bc6.js","fe6a6277acaa2a369ef235961be7bbcf"],["route.admin.CleanupPage.8b4bbf8e.js","8ab20412329e1ba4adc327713135be97"],["route.app.CmsPage.8a4303fb.js","0bf1506869db24bb9789c8a46449c8ad"],["route.app.CmsPageWrapper.accdebcc.js","c91e77aa8b518e1878761269deac22b6"],["route.app.ContactPage.75693d32.js","a530b00a5230a44897c2bf0aa9f402a8"],["route.app.PasswordResetExpiredDialog.65431bae.js","b5eef791dbd68edd4769bd6da022a857"],["route.app.SeriesDetailsPage.11a6989b.js","c52178b57767ae1bf94a9594cb32718e"],["route.cms.MetadataFormsPage.636188d2.js","e1e592b7e3dd82af774ac215524465c0"],["route.cms.PermissionsListPage.0e1e3075.js","9a3cc340a64238a1ab3ba1c0d483b7bd"],["route.cms.PermissionsPage.78a69f60.js","4b18e646715d6268e7aba3932f4e04a9"],["route.cms.SysconfigPage.f699b871.js","79bd1275213478f2ff1970e0b7341c49"],["styles.43e29bc620615f854714.css","b2e9e55e9ee2def2ae577ee1aaebda8f"],["styles.e0c12bb1c77e645e92d3.css","626778177949d72221e83b601c6c2c0f"],["translations.en.83fced0e.js","7e5509c23b5aafc1744a28a85c2950bb"],["translations.nl.4ae0b3bb.js","515ec7be7352a0c61e4aba99f0014a39"],["vendor.e0c12bb1.js","36ce9e0a59c7b4577b2ac4a637cb4238"]];
var cacheName = 'sw-precache-v3-nisv-client-' + (self.registration ? self.registration.scope : '');

问题:

  • 为什么“新的或更新的内容”案例经常发生?
  • 假设case 'installed': if (navigator.serviceWorker.controller) {是否正确case 'installed': if (navigator.serviceWorker.controller) {意味着New or updated content is available
  • 我该如何调试问题?

服务人员的生命周期

- registered
- installing
- installed
- waiting
- activated
- redundant

注册服务工作程序时,它是从服务器获取的,它在disk缓存中的生命周期取决于Web服务器发送它的cache-control响应头。

具有cache-control : no-store must-revalidate被认为是最佳实践cache-control : no-store must-revalidate以及max-age : 0如果可能)。

如果您忘记了,服务工作者通常会在注册24小时后被认为是stale的,并且会被refetched并更新磁盘缓存。

您可以通过在服务工作者上升级cache版本或更改服务工作者代码来进行手动升级。 即使是一个byte变化使得浏览器view服务工作者作为一个新的,并安装新的服务人员。

然而,这并不意味着旧的服务工作者被丢弃。 任何用户必须关闭所有选项卡/ 导航离开您的站点,浏览器要丢弃旧服务工作者,并激活新服务工作者。

您可以通过install handlerself.skipWaiting绕过此行为

那说,

开发时,您可以选择打开浏览器(铬)开发面板,导航到application选项卡,然后选中显示的框

update on reload

这样做,无论您的服务工作者代码是否有变化, 立即丢弃旧服务工作者。

关于你的问题:

  • 假设“安装”的情况是否正确:if(navigator.serviceWorker.controller){意味着新的或更新的内容是否可用?

没有。 这意味着,安装了新服务工作者,例如sw-v1,并且当前正在waiting激活。

  • 为什么“新的或更新的内容”案例经常发生?

你说,你正在使用sw-precache 因为,我自己没有使用它,我必须补充一个反问题

  • 是否已配置插件,以获取静态资产的更改,并自动触发service-worker的代码更改或缓存冲突?

如果是这样,那么,任何新版本的服务工作者必须只waiting而不是activating更改。

skipping等待阶段的可能原因是,

  • 你在服务工作者的install事件中有一个self.skipWaiting

注意以上情况属实,仅限于

  • 发生了对您的内容的更改。
  • 该更改会触发服务工作者更新

在这种情况下,您可能需要考虑注释掉self.skipWaiting语句。 或者,也许你可以配置你的插件,不要跳过更新 - 这对你的内容很重要,你需要接听电话

代替您的资产更改和/或触发更新的事实,

其他(最可能的)原因必须是,

您在开发控制台上的application - > service workers选项卡下检查update on reload框的update on reload

取消选中该框,如果选中,则清除所有缓存,取消注册所有工作人员。 之后,打开一个新选项卡并继续测试该行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM