title: How to refresh the page after a ServiceWorker update?
body: <p>I've consulted a lot of resources on Service Workers:</p>
  
  <ul>
  <li><a href="https://jakearchibald.com/2014/using-serviceworker-today/#updating-your-serviceworker" rel="noreferrer">Updating your ServiceWorker</a></li>
  <li><a href="https://ponyfoo.com/articles/serviceworker-revolution" rel="noreferrer">ServiceWorker: Revolution of the Web Platform</a></li>
  <li>Jake Archibald's lovely <a href="https://github.com/jakearchibald/svgomg/blob/6c21157b65dd779bbf2dd2adf9831aaf71d4bb08/src/js/sw/index.js" rel="noreferrer">SVGOMG</a>. </li>
  </ul>
  
  <p>However, I can't for the life of me figure out how to update the page after a new ServiceWorker has been installed. No matter what I do, my page is stuck on an old version, and only a hard refresh (Cmd-Shift-R) will fix it. No combination of 1) closing the tab, 2) closing Chrome, or 3) <code>location.reload(true)</code> will serve the new content.</p>
  
  <p>I have a <a href="https://github.com/nolanlawson/serviceworker-update-demo" rel="noreferrer">super simple example app</a> mostly based on SVGOMG. On installation, I cache a bunch of resources using <code>cache.addAll()</code>, and I also do <code>skipWaiting()</code> if the current version's major version number doesn't match the active version's number (based on an IndexedDB lookup):</p>
  
  
  
  <pre><code>self.addEventListener('install', function install(event) {
    event.waitUntil((async () =&gt; {
      var activeVersionPromise = localForage.getItem('active-version');
      var cache = await caches.open('cache-' + version);
      await cache.addAll(staticContent);
      var activeVersion = await activeVersionPromise;
      if (!activeVersion ||
        semver.parse(activeVersion).major === semver.parse(version).major) {
        if (self.skipWaiting) { // wrapping in an if while Chrome 40 is still around
          self.skipWaiting();
        }
      }
    })());
  });
  </code></pre>
  
  <p>I'm using a semver-inspired system where the major version number indicates that the new ServiceWorker can't be hot-swapped for the old one. This works on the ServiceWorker side - a bump from v1.0.0 to v1.0.1 causes the worker to be immediately installed on a refresh, whereas from v1.0.0 to v2.0.0, it waits for the tab to be closed and reopened before being installed.</p>
  
  <p>Back in the main thread, I'm manually updating the ServiceWorker after registration &ndash; otherwise the page never even gets the memo that there's a new version of the ServiceWorker available (oddly I found very few mentions of this anywhere in the ServiceWorker literature):</p>
  
  
  
  <pre><code>navigator.serviceWorker.register('/sw-bundle.js', {
    scope: './'
  }).then(registration =&gt; {
    if (typeof registration.update == 'function') {
      registration.update();
    }
  });
  </code></pre>
  
  <p>However, the content that gets served to the main thread is always stuck on an old version of the page ("My version is 1.0.0"), regardless of whether I increment the version to 1.0.1 or 2.0.0.</p>
  
  <p>I'm kind of stumped here. I was hoping to find an elegant semver-y solution to ServiceWorker versioning (hence my use of <code>require('./package.json').version</code>), but in my current implementation, the user is perpetually stuck on an old version of the page, unless they hard-refresh or manually clear out all their data. :/</p>