26

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) location.reload(true) 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 cache.addAll(), and I also do skipWaiting() 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 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(); } } })()); }); 

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') { registration.update(); } }); 

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 require('./package.json').version), 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. :/

1
  • I can't find steps you've done to ensure the new Service Worker has been installed. You claim but have not ensured that it really has been installed. Commented Feb 18, 2018 at 21:32

3 Answers 3

28

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: https://github.com/nolanlawson/serviceworker-update-demo/pull/1

Cheers to Jake Archibald for setting me straight: https://twitter.com/jaffathecake/status/689214019308224513

Sign up to request clarification or add additional context in comments.

4 Comments

does changing the max-age =0 have any negative effects?
Thanks for this, I've been having the same problem. I'm using the http-server npm package and learned after reading this that it sets max-age=2600 by default. Starting the server using -c-1 disables that so your service worker behaves more predictably. eg. http-server -c-1 -p 8081
@JamieMason Where do I add this line in serviceWorker file? max-age=0
@AnthonyWinzlet max-age is a header returned by a web server when serving a file, in this case the service worker js file when the server is sending it to the client. It is not something you set in the service worker file itself, but rather on the server-side that is hosting/serving it. See: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/….
5

External: stop and unregister a service worker using chrome://serviceworker-internals/

Internal from service worker itself: https://developer.mozilla.org/en-US/docs/Web/API/Clients/claim and https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting

1 Comment

Not quite... I'm already doing that here: github.com/nolanlawson/serviceworker-update-demo/blob/…
2

In Chrome Canary you can do all sort of Service Worker profiling and management like unregister, clear in the Applications Tab:

enter image description here

Pair that with chrome://devices/ to debug with your physical device.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.