skipWaiting() 没有安装卡在等待阶段的新 Service Worker

Nis*_*sai 5 updating reactjs service-worker progressive-web-apps workbox

我正在创建一个 PWA,我想在更新的 Service Worker 可用时提示用户,但无论我是打电话skipWaiting()还是skipWaiting在开发控制台中手动按下,它都会陷入等待阶段。

只有当我首先停止现有的 Service Worker 时,才会安装新的 Service Worker。

我也尝试通过self.skipWaiting()在安装阶段直接调用来强制安装,但我更新后的 Service Worker 仍然陷入等待阶段。

这是我的设置。

sw.js

// when installing hydrate caches and notify user that reload if required (if any)
self.addEventListener('install', async () => {
    // self.skipWaiting();
    await hydrateCache();
});

self.addEventListener('message', (message) => {
    if (message.data === 'skipWaiting') {
        debugger;
        self.skipWaiting();
    }
});
Run Code Online (Sandbox Code Playgroud)

索引.html

navigator.serviceWorker.register('sw.js')
  .then(function (reg) {
     reg.onupdatefound = function() {
       var newServiceWorker = reg.installing;

       if (reg.waiting && confirm('Updates are available, Would you like to reload?')) {
          newServiceWorker.postMessage('skipWaiting');
       }

       newServiceWorker.onstatechange = function() {
         // for some reason I am not getting waiting state update so I am prompting user
         // when client gets installed phase update
         if (newServiceWorker.state === 'installed') {
           if (confirm('Updates are available, Would you like to reload?')) {
             newServiceWorker.postMessage('skipWaiting');
           }
         }
       }
     }

     navigator.serviceWorker.addEventListener('controllerchange', function() {
       window.location.reload();
     });        
   })
   .catch(function (err) {
     console.error('register err', err);
   });
Run Code Online (Sandbox Code Playgroud)

我期望每当我向skipWaiting服务工作者发送消息时,它应该替换现有的服务工作者,我的代码确实会调用,self.skipWaiting()但在开发控制台中,我更新后的服务工作者仍处于等待阶段,即使我手动按下skipWaiting它也不会替换现有的服务工作者。

当前网站

更新:

因此,在修改我的代码后,我发现了一件有趣的事情,'fetch'即使我调用了skipWaiting()call.

此代码不会让新的 Service Worker 被激活

// intercept fetch requests and responds with cached file if they are available like CDN Files
self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches.match(event.request)
            .then((response) => {
                if (response) {
                    console.log('Found ', event.request.url, ' in cache');
                    return response;
                }

                console.log('fetching', event.request.url, 'from internet');
                return fetch(event.request);
            })
            .catch((err) => {
                console.error('fetch error', err);
            }),
    );
});
Run Code Online (Sandbox Code Playgroud)

如果我从'fetch'偶数处理程序中删除我的自定义代码,当我调用skipWaiting(). 'fetch'一旦我的工作人员拦截了一个请求,我基本上不会对我的处理程序做任何事情,它会直接尝试从互联网上获取它。

self.addEventListener('fetch', (event) => {
    return fetch(event.request);
});
Run Code Online (Sandbox Code Playgroud)