polymerservice-workerfirebase-polymerpolymer-clisw-precache

Service Worker: How to build "Fresh" version of website for each new deployment?


The Problem

I'm having an issue with a website (built w/ the Polymer Shop template) in production that's serving up old versions of code despite my new and improved deployments.

I'm using the Polymer CLI $ polymer build command along w/ the Firebase Tools $ firebase deploy command to push up changes to Firebase Hosting. After deploy is complete, I navigate to the website only to see the changes not updating:


Here's the before n' after shot:

enter image description here


Service Worker workflow?

I'm trying to figure out what the best workflow is for this. I want to set things up so that every time I make a new deploy, the entire site is wiped clean and the service worker resets itself through the inter webs and I'll be 100% sure that existing users will get that newly deployed experience

with out having to hard refresh or use incognito mode.


Should I...


I know that the problem exists inside the sw-precache-config.js file, but I'm unsure if this is where I should be fixing this.

module.exports = {
  staticFileGlobs: [
    '/index.html',
    '/manifest.json',
    '/bower_components/webcomponentsjs/webcomponents-lite.min.js',
    '/images/*'
  ],
  navigateFallback: '/index.html',
  navigateFallbackWhitelist: [/^(?!.*\.html$|\/data\/).*/],
  runtimeCaching: [
    {
      urlPattern: /\/data\/images\/.*/,
      handler: 'cacheFirst',
      options: {
        cache: {
          maxEntries: 200,
          name: 'items-cache'
        }
      }
    },
    {
      urlPattern: /\/data\/.*json/,
      handler: 'fastest',
      options: {
        cache: {
          maxEntries: 100,
          name: 'data-cache'
        }
      }
    }
  ]
};

The Service Worker is an amazing tool and I definitely want it in my projects. I just need to learn how to tame the beast.


Solution

  • I don't know about polymer, but this is the flow I usually do with service workers.
    - In the client I check if there is a update, the app notify the user if he/she wants to update.
    - User accepts new version, then client send a message to sw to skipWating.
    client.js:

    navigator.serviceWorker.register('/serviceWorker.js').then(function(reg) {
        reg.addEventListener('updatefound', function() {
    
          reg.installing.addEventListener('statechange', function() {
    
            if (reg.installing.state == 'installed') {
              // Notify the user, there is a app new version.
              // User accept
               reg.installing.postMessage({msg: 'skipwaiting'});
            }
          });
        });
    });
    

    -In the service worker listen for the message and skipWating if user accepts the new version.
    serviceWorker.js:

    self.addEventListener('message', function(event) {
      if (event.data.msg === 'skipwaiting') {
        self.skipWaiting();
      }
    });
    

    The client refresh the application after the service worker has change state. client.js:

    let refreshing;
    
    navigator.serviceWorker.addEventListener('controllerchange', function() {
        if (refreshing) 
        return;
        window.location.reload();
        refreshing = true;
    });
    

    Maybe this can give you an idea.