Service Workers

A script running independently of any page that intercepts network requests, enabling deliberate offline strategies.

                navigator.serviceWorker.register("/sw.js") / self.addEventListener("fetch", handler)
              

Purpose

A service worker is a script that runs separately from any page, capable of intercepting every network request the pages under its control make and deciding how to respond — from the network, from a cache, or a combination — enabling offline support.

Syntax

// Registered from a page:
navigator.serviceWorker.register('/sw.js');

// sw.js:
self.addEventListener('install', (event) => {
  event.waitUntil(caches.open('v1').then((cache) => cache.addAll(['/', '/styles.css'])));
});

self.addEventListener('fetch', (event) => {
  event.respondWith(caches.match(event.request).then((cached) => cached || fetch(event.request)));
});

Behavior notes

  • A service worker’s lifecycle is independent of any one page — it persists across reloads once installed, and can outlive the closing of the page that registered it.
  • It requires HTTPS (or localhost for development) — a security requirement, since a service worker can intercept and modify every request a page makes.
  • Different strategies suit different resources: cache-first for assets that rarely change, network-first-with-cache-fallback for data that should be fresh when possible but usable offline, stale-while-revalidate for a middle ground (serve cached immediately, update the cache in the background).
  • A new version of a service worker installs alongside the old one and only takes over once every open tab using the old version has closed, unless explicitly told to activate immediately (self.skipWaiting()).

Common mistakes

  • Caching a response indefinitely with no update strategy, leaving users stuck on stale content after a deploy.
  • Forgetting that fetch events only fire for requests from pages under the service worker’s control (its registration scope) — not every request on the origin.

Runtime notes

Standard in every current browser; no equivalent in Node, which has no page/service-worker relationship to intercept.

Taught in these lessons

Related reference