I still struggle how to avoid caching problems in Progressive Web Apps. Crucial for any PWA caching is the ability to update the ServiceWorker file (let's call it sw.js). But the details are a bit confusing to me:
It's okay to execute navigator.serviceWorker.register('sw.js')
on every page load because register()
updates the app cache or does nothing if everything is up to date -- correct?
Does it make sense to do something like navigator.serviceWorker.register('sw.js?' + Date.now())
to avoid HTTP caching? Or am I on the safe side if the server uses ETags?
Does the browser check the network for an updated sw.js on every pageload? I sometimes don't see it in the network inspector tab.
If sw.js is in the app cache, does the browser fetch it from there without checking the server for an update?
I sometimes see ServiceWorker demo scripts that cache themselves like this:
self.addEventListener('install', ev => {
const myCaches = {
app: {...},
sw: {
files: [
'/sw.js'
],
version: '1'
}
}
for (let name in myCaches) {
const cacheName = name + '-' + myCaches[name].version
ev.waitUntil(
caches.has(cacheName).then(uptodate => {
if (uptodate) return true
caches
.open(cacheName)
.then(cache => {
cache.addAll(myCaches[name].files)
})
})
)
// clear old caches
}
})
Does this make sense, is it good practice? Does it make updating the cache more reliable?
Most of the code examples I've seen don't add the service worker file to the cache. In my experience and from my understanding, it's not necessary for offline mode to work.
The browser will install your service worker for your PWA when you register it. The browser uses a separate facility for caching and managing service workers. It's not your responsibility to cache it.
Adding a timestamp to the filename of your service-worker is an anti-pattern. According to the article on Service Worker Lifecycle, you should avoid changing the URL of your service worker script.
What is of greater concern is the point you raised about updating the service worker, how does the browser know when to do that?
Well, according to the section Updating the service worker from the Service Worker Lifecycle article:
Most browsers, including Chrome 68 and later, default to ignoring caching headers when checking for updates of the registered service worker script. They still respect caching headers when fetching resources loaded inside a service worker via
importScripts()
. You can override this default behavior by setting theupdateViaCache
option when registering your service worker.Your service worker is considered updated if it's byte-different to the one the browser already has. (We're extending this to include imported scripts/modules too.) The updated service worker is launched alongside the existing one, and gets its own
install
event.If your new worker has a non-ok status code (for example, 404), fails to parse, throws an error during execution, or rejects during install, the new worker is thrown away, but the current one remains active.
If you've tested your PWA in offline mode, you'll notice that the browser will produce an error in the console when it tries to retrieve your sw.js
file. That's nothing to be concerned about. As the last point above says, "the current one remains active".
I wonder if people are fixated on this 404 entry in the console for the service worker JavaScript when they test in offline mode and add the service worker file to the cache in a fit of yak shaving? It probably does a disservice to your site and its users by spending time and disk caching an unnecessary file in the browser.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With