why service worker download new content automatically, but doesn't update?

Viewed 594

I register service worker this way:

/* eslint-disable no-console */

import { register } from 'register-service-worker'

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    ready() {
      console.log('App is being served from cache by a service worker.');
    },
    registered() {
      console.log('Service worker has been registered.');
    },
    cached() {
      console.log('Content has been cached for offline use.');
    },
    updatefound() {
      console.log('New content is downloading.');
    },
    updated() {
      console.log('New content is available; please refresh.');
    },
    offline() {
      console.log('No internet connection found. App is running in offline mode.');
    },
    error(error) {
      console.error('Error during service worker registration:', error);
    }
  });
}

when I vue-cli-service build --mode production and then I deploy to the server, online I can correctly see the logs:

App is being served from cache by a service worker.
Service worker has been registered.
New content is downloading.
New content is available; please refresh.

It seems to download automatically the content, but from now, it still always show New content is available; please refresh (and in fact, the content is not refreshed). It seems it won't refresh automatically? Only downloading? Why?

How can I refresh on updated()?

2 Answers

what I did in this situation was to resolve a promise that will reload the page for the user. This is nice because it waits and then does the page reload after the data has come in.

/* eslint-disable no-console */

import { register } from 'register-service-worker'

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    ready() {
      console.log('App is being served from cache by a service worker.');
    },
    registered() {
      console.log('Service worker has been registered.');
    },
    cached() {
      console.log('Content has been cached for offline use.');
    },
    updatefound() {
      console.log('New content is downloading.');
    },
    updated() {
      console.log('New content is available; please refresh.');
      Promise.resolve().then(() => { window.location.reload(true); });
    },
    offline() {
      console.log('No internet connection found. App is running in offline mode.');
    },
    error(error) {
      console.error('Error during service worker registration:', error);
    }
  });
}

you should use skipWaiting method of service worker object.

maybe this can help you:

updated(registration){
    const waitingServiceWorker = registration.waiting;

    if (waitingServiceWorker) {
      waitingServiceWorker.addEventListener('statechange', event => {
        if (event.target.state === 'activated') {
          window.location.reload();
        }
      });
      waitingServiceWorker.postMessage({ type: 'SKIP_WAITING' });
    }
}

whether this code is working or not depends on your service-worker.js content.

but the idea is the same you should use skip waiting.

Related