nlawson nlawson - 4 months ago 7x
Javascript Question

How to refresh the page after a ServiceWorker update?

I've consulted a lot of resources on Service Workers:

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)
will serve the new content.

I have a super simple example app mostly based on SVGOMG. On installation, I cache a bunch of resources using
, and I also do
if the current version's major version number doesn't match the active version's number (based on an IndexedDB lookup):

self.addEventListener('install', function install(event) {
event.waitUntil((async () => {
var activeVersionPromise = localForage.getItem('active-version');
var cache = await'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

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.

Back in the main thread, I'm manually updating the ServiceWorker after registration – 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):

navigator.serviceWorker.register('/sw-bundle.js', {
scope: './'
}).then(registration => {
if (typeof registration.update == 'function') {

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.

I'm kind of stumped here. I was hoping to find an elegant semver-y solution to ServiceWorker versioning (hence my use of
), 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. :/


Found the issue – you need to avoid any cache headers on the ServiceWorker JS file itself. Setting the cache to max-age=0 immediately solved the problem:

Cheers to Jake Archibald for setting me straight: