Service worker update delay

2019-04-15 06:08发布

问题:

I have a web app that is working and relying on service workers to keep all the cached files in check and to make sure users are on the correct version of the app.

Our client is currently wanting the device to check for an update at specific points (When reopening the app) etc, as currently when you open the app it can take up to 5minutes before the device realises its on an outdated version.

Am I able to force the device to check the service worker for any new changes instead of waiting for the app to check for me?

Thanks!

回答1:

There are two main points you should refine for instant update of your SW.

Shortly

  1. Call your sw.jsalso from more often visited pages than your app's index page.
  2. Utilize skipWaiting() method to activate your SW instantly.

In detail

1) navigator.serviceWorker.register method call

You should note that newer verison of the SW will only be checked by a navigator.serviceWorker.register() call.

And typically register() method will be called in one of your pages only. If that is the case, you should add that command to all of your pages. Because if user just opens another app without closing your PWA and then returns to your app after, say 2 hours, they will avoid the index page of the app where your register() call probably is.

So, my suggestion is to put it to many pages if not every. Downside is clients will make much more calls to sw.js. Upside is clients will retrieve last version of SW without losing time.

2) Activating service worker

Service Worker's activate event will be called when SW no longer has any active clients. So new version will be activated only after every instance of the app but one closed, and the remaining tab is refreshed/one tab re-opened. See quote from MDN about the matter:

..the new version is installed in the background, but not yet activated. It is only activated when there are no longer any pages loaded that are still using the old service worker. As soon as there are no more such pages still loaded, the new service worker activates.

And solution to this one would be using skipWaiting() method in conjunction with Clients.claim()

Usage example of those taken from MDN. Click to see more about it on that page:

self.addEventListener('install', function(event) {
  event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', function(event) {
  event.waitUntil(self.clients.claim());
});