vuejs-templates / pwa

PWA template for vue-cli based on the webpack template
MIT License
3.04k stars 508 forks source link

Service worker does not recognize update #181

Closed leonardovilarinho closed 6 years ago

leonardovilarinho commented 6 years ago

Hello,

I have an application that works offline with SWPrecacheWebpackPlugin, but it keeps saving the cache too much. When I release a new version I have to reload the system about 5 times to update.

I saw that I can post a notification when I receive an update from the service worker. I tried but it did not work, can you help me?

In webpack.prod.conf.js I have the cache configuration:

new SWPrecacheWebpackPlugin({
  cacheId: `${env.APP_NAME}-${env.APP_VERSION}`,
  filename: 'service-worker.js',
  staticFileGlobs: ['dist/**/*.{js,html,css,svg,png,jpg,jpeg,woff}'],
  minify: true,
  stripPrefix: 'dist/',
  runtimeCaching: [
    {
      urlPattern: /^http:\/\/localhost\//,
      handler: 'cacheFirst'
    },
    {
      urlPattern: /^https:\/\/cdnjs\.cloudflare\.com\//,
      handler: 'cacheFirst'
    }
  ]
})

Now in service-worker-prod.js when there is an update try to show a notification on the screen asking the client to update the site:

(function () {
  'use strict';
  var isLocalhost = Boolean(
    window.location.hostname === 'localhost' ||
    window.location.hostname === '[::1]' ||
    window.location.hostname.match(
      /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
    )
  );

  window.addEventListener('load', function () {
    var hasSWSupport = 'serviceWorker' in navigator;
    var isHttps = window.location.protocol === 'https:';
    var isValidHost = (isHttps || isLocalhost);

    if (hasSWSupport && isValidHost) {

      navigator.serviceWorker
      .register('service-worker.js')
      .then(function (registration) {

        console.log('registration ok');
        registration.onupdatefound = function () {

          var installingWorker = registration.installing;
          console.log('update has founded');

          installingWorker.onstatechange = function () {

            console.log('update status has changed', installingWorker.state);
            if (installingWorker.state === 'installed') {

              if (navigator.serviceWorker.controller) {
                console.log('please, update your app');
                var updater = document.getElementById('updater');
                updater.style.display = 'block';
              }
              else {
                console.log('control not found');
              }

            }
          };

        };

      }).catch(function (e) {
        console.error('Error during service worker registration:', e);
      });
    }

  });

})();

PS: I've put some logs to understand better, and the updater element is a Vue component.

When running the system for the first time, I have the logs:

(index):1 registration ok
(index):1 update has founded
(index):1 update status has changed installed
(index):1 control not found
(index):1 update status has changed activating
(index):1 update status has changed activated

So I edit something in some Vue component and build again, upon entering the page again I expected to be notified of the new version, but I only have the log:

(index):1 registration ok

I expected something like this:

(index):1 registration ok
(index):1 update has founded
(index):1 update status has changed installed
(index):1 please, update your app
(index):1 update status has changed activating
(index):1 update status has changed activated

What can I be missing?

jeffposnick commented 6 years ago

Are you serving your service-worker.js file with HTTP caching enabled? That would lead to the behavior you're seeing in browsers other than Firefox. See https://stackoverflow.com/questions/38843970/service-worker-javascript-update-frequency-every-24-hours/38854905#38854905 for more details.

(vue-cli v3 will use Workbox instead of sw-precache under the hood, and Workbox will log a warning to the JS console when you have HTTP caching enabled for your service-worker.js file. And as mentioned in that SO answer, in the future, Chrome and other browsers will start ignoring the HTTP caching settings for your service worker file like Firefox does.)

leonardovilarinho commented 6 years ago

Hi, @jeffposnick

I do not know if I understood, however I created a new project with the vue-cli 3 + pwa. By default the workbox did the caching, but then I tried to edit something in a compenente and compile it again. And it never runs the updated register-service-worker method.

From what I understand it would be because of HTTP caching, how would I change it now? And make it work?

leonardovilarinho commented 6 years ago

I was able to solve it, I removed my services workers from pre-cache, like this:

staticFileGlobsIgnorePatterns: [/dist\/*-worker\.js/],