Letting PWA users know there's new code ready
Progressive Web Apps are, if nothing else, an exercise in cache management. Do it right and everybody is happy. Do it wrong and the ghost of app past may haunt a user until they buy a new phone.
The first thing you need to do is prevent your browser cache from engaging in hand-to-hand combat with your service worker cache. Specifically, do not cache service-worker.js
. That sucker needs to pull a Mission Impossible and self immolate after opening. In Nginx, your caching strategy would look something like this:
1 | # cache settings |
If your service worker is cached in the browser, you end up having to do weird stuff to refresh, like close the actual browser tab and open it again. When you CTRL-F5 with the service worker cached, the browser basically laughs at you until the tab itself goes away. It knows there’s new content. But it hates you.
Once you have that straightened out, you’re still stuck with the issue of a service worker loading new content but not actually doing anything with it until the user refreshes the page. This isn’t terrible, unless the new code fixes a bug, in which case it is in fact terrible.
I took a page from the Vue CLI docs here. They give a notice when there’s new content available with a button that essentially does a location.reload(true)
. You can roll that by hand, but if you’re using a convenience library like register-service-worker, it’s a bit easier.
Your default register-service-worker
code looks like this:
1 | import { register } from 'register-service-worker' |
Aside from very convenient log messages, this gives you a nice updated
hook you can use to send the user a message. In index.html
I have a little message on the bottom of the screen with a hidden
class so it doesn’t display by default.
1 | <!-- service worker detected update --> |
This has two buttons, one to dismiss by slapping a hidden
class back on the parent, and one to reload the page. It looks like this:
In my service worker registration I add this line to the updated
hook to show the update notification:
1 | updated(registration) { |
This message is only shown when the service worker is done loading the update, and clicking reload gets the user up to snuff. If a user doesn’t want to reload then, they don’t have to. While it would be easier to stick location.reload(true)
directly in the service worker updated
hook and be done with it, since it may take a few moments after page load for the service worker to register and download updates, you’ll essentially yank the rug out from under your users mid page-oggle. I’m sure there’s a proper UX phrase for that but I’d just call it bad manners.