How to refresh the page after a ServiceWorker update?
<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>