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
localhostfor 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
fetchevents 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.