Service workers

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the web-development category.

Last Updated: 2024-04-25

What is it?

Service Worker is a piece of JavaScript that works as a single controller & network proxy for all the instances of our application. That means that all the browser windows share the same active Service Worker.

Service Worker Lifecycle

1. Register

When the user visits the website this begins.

The browser downloads, parses and executes the service worker.

2. Install

Happens as soon as the service worker executes

3. Activate

At this point, the service worker can control clients and handle functional events

Updating existing code

It cannot be seamlessly updated as long as there is any window or tab that it serves. This is esp. an issue with long-running stuff like messengers etc. Service Worker will be never updated, even though the browser might already have detected the pending update.

Moreover, simple refreshing is not sufficient to make room for the new Service Worker to take over, even if there's only one tab of our application running. This is because browsers do not unload the earlier instance of the website immediately when we request the refresh – for some time the new instance being loaded exists simultaneously in the memory next to the previous one, being unloaded.

Hard-refresh (Control+Shift+R-kind) is sufficient (because it bypasses the Service Worker), but we can't expect our users to use it for the ordinary browsing

Fortunately, there is a programmatic way for the waiting Service Worker (the one that we received and installed as the newly updated controller of our app) to take over control over the existing clients. We can call self.skipWaiting() from within the new Service Worker – it immediately stops the previously active Service Worker and activates the new one, so that all the currently opened windows will be served by the new one. Downside: All the already opened windows were loaded with the help of the previous Service Worker that potentially used different versions of the assets - esp. bad if we use code-splitting or other lazy loading techniques

Fetch interception

You'll see "(service worker)" in the "size" column of th networks tab. Then you'll see an extra entry with a gear icon to its right prefixing it and an intiator being something like "sw.js".

This request may or may not be cached.

Caching

The service worker has its own cache (IndexedDB or Cache Storage API) that can be used separate to the HTTP caching of the browser.

Resources

Debugging in DevTools

To see requests intercepted go the Application > Network Requests. You'll notice a filter is added "is:service-worker-intercepted"

Console.log is not available normally - you must go to chrome://serviceworker-internals/, find the service worker (e.g. for localhost) and click "inspect"