javascriptwebpackprogressive-web-appsservice-workerapp-update

service-worker new version detected does not call skipWaiting()


Description

In a Web Application, we use a service-worker for a few task such as:

  1. PWA
  2. Web push
  3. detecting when new version has been published and if yes, reload to the newest version

We decided to remove Web push feature, this cause the service worker to have a new version.

This is the commit commit.

    self.skipWaiting()
  }
})
-
- // This will add batch sdk service worker
- self.importScripts(process.env.PUBLIC_URL + '/batchsdk-shared-worker.js')

For some reason, we never go through the event that call skipWaiting(): https://github.com/pass-culture/pass-culture-app-native/blob/master/src/service-worker.ts#L76

// This allows the web app to trigger skipWaiting via
// registration.waiting.postMessage({type: 'SKIP_WAITING'})
self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting()
  }
})

This is the state of our app when detecting the new version

image

If I click on skipWaiting in the developer tab, then the update perform normally.

Expected result

On a new release:

  1. Of the application without change to the service worker: the event gets called and we call self.skipWaiting()
  2. Of the service worker: it should also call skipWaiting()

Actual result

(1) works as expected, the skipWaiting() is called, however, when we are in (2), the release of a new version of our service worker detect the update but skipWaiting() is never called.

Question

In the case of a new service worker version, how can we call skipWaiting() to update the service worker automatically ?


Solution

  • When a new app is published, the new service worker automatically detect the new webapp, but it does not install this, for this, you must call sw.skipWaiting(), either automatically or using a button.

    This was working with the following code within the service worker:

    self.addEventListener('message', (event) => {
      if (event.data && event.data.type === 'SKIP_WAITING') {
        self.skipWaiting()
      }
    })
    

    However, it is working only if the chunks of our application change. In case of a modification of the service worker (and new version of it, not the webapp), then this event is not triggered. I manage to fix this, by adding in our service worker the following:

    self.addEventListener('install', () => {
      self.skipWaiting()
    })
    

    New service worker needs to install and thus emit an install event.