salonMonsters
salonMonsters

Reputation: 1287

PWA Service worker caching / updating expected behaviour

I'm trying to get my head around service worker caching for an Ionic Angular app.

My goal is to make an alert pop up: "New update available, click to reload the app",

I believe I've followed all the correct practices based on my reading but am missing something as I am unable to reliably get the alert to pop up after an update. It will pop up but can take up to 24 hours - is the expeced behaviour?

I am using four files:

In service-worker.js I:

.

'use strict';
importScripts('./build/sw-toolbox.js');

self.toolbox.options.cache = {
  name: 'my-cache'
};

const CACHE_VERSION = 1;

self.toolbox.router.get('assets/*', self.toolbox.cacheFirst);
self.toolbox.router.get('build/*', self.toolbox.networkFirst);
self.toolbox.router.get('/', self.toolbox.networkFirst);
self.toolbox.router.get('manifest.json', self.toolbox.networkFirst);

In index.html I:

.

 <script>
    // make the whole serviceworker process into a promise so later on we can
    // listen to it and in case new content is available a toast will be shown
    window.isUpdateAvailable = new Promise(function(resolve, reject) {
      // checks if serviceWorker is supported and disable service workers while developing
      if ('serviceWorker' in navigator && ['localhost', '127'].indexOf(location.hostname) === -1) {
        // register service worker file
        navigator.serviceWorker.register('service-worker.js')
          .then(reg => {
            reg.onupdatefound = () => {
              const installingWorker = reg.installing;
              installingWorker.onstatechange = () => {
                switch (installingWorker.state) {
                  case 'installed':
                    if (navigator.serviceWorker.controller) {
                      // new update available
                      console.log("new update available");
                      resolve(true);
                    } else {
                      // no update available
                      resolve(false);
                      console.log("up to date");
                    }
                    break;
                }
              };
            };
          })
          .catch(err => console.error('[SW ERROR]', err));
      }
    });
  </script>

In myapp.page.ts I followed this article: https://medium.com/progressive-web-apps/pwa-create-a-new-update-available-notification-using-service-workers-18be9168d717:

.

public ngOnInit () {

    // listen to the service worker promise in index.html to see if there has been a new update.
    // condition: the service-worker.js needs to have some kind of change - e.g. increment CACHE_VERSION.
    window['isUpdateAvailable']
      .then(isAvailable => {
        if (isAvailable) {

          console.log('Update is available');

          const alert = this.alertController.create({
            title: 'New Update available!',
            message: 'Please reload the app to continue.',
            buttons: [
            {
              text: 'Reload',
              handler: () => {
                caches.delete("my-cache");
                location.reload(true);                
              }
            }]
          });
          alert.present();
        }
      });
  }

In .htaccess I:

.

  <Files service-worker.js>
    <IfModule mod_headers.c>
        Header set Cache-Control "no-cache, no-store, must-revalidate"
        Header set Pragma "no-cache"
        Header set Expires 0
    </IfModule> 
</Files>

Then I increment the const CACHE_VERSION value to cause the change in the service-worker.js file.

My expectation is that when I increment the CACHE_VERSION and return to an already open version (tab) of the app or open a new tab of the app it should pop up the alert or at least console log that there is an update. This isn't happening right away and instead can take up to a day to happen.

Is this the expected behaviour or am I missing something? Thanks!

Upvotes: 2

Views: 2606

Answers (1)

salonMonsters
salonMonsters

Reputation: 1287

The service worker is not updated until the page is reloaded.

To make it update the service worker without the user reloading the page you can use the service worker's update() method: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/update

For example to check for a new service worker every half hour:

 setInterval(() => {
    console.log("force check our service-worker from the server")
    reg.update();
 }, 1800000);

Upvotes: 1

Related Questions