Service Workers: Lifecycle (Install, Activate), Cache Storage, and Fetch Interception
- Last updated
- Prerequisites:
- Web Workers architecture
- HTTP Caching and Fetch API
- browser
- service-worker
- pwa
- offline
- cache-storage
- fetch
Read at your depth
The practical view
A Service Worker is an event-driven background worker running on its own origin-scoped thread. Its lifecycle has three main phases: Registration, Installation (`install` event where you pre-cache static assets), and Activation (`activate` event where you purge outdated caches). Once active, it intercepts all network calls from controlled pages via the `fetch` event using `event.respondWith(caches.match(event.request))`.
The same idea in other frameworks
Workbox / PWA plugin registering precache manifests inside `serviceWorker.register()`.`@angular/pwa` using `ngsw-config.json` for declarative asset caching.Vite PWA plugin (`vite-plugin-pwa`) managing service worker generation.SvelteKit `src/service-worker.js` with built-in `$service-worker` asset imports.Legacy vs modern
Network-Only Fetch vs Offline Cache-First Interception
Standard web pages fail with a dinosaur error offline; a Service Worker intercepts requests and serves cached assets instantly.
fetch('/api/data'); // ❌ Crashes immediately when user is offlineevent.respondWith(caches.match(event.request)); // ✅ NEW: Instant offline capabilityInterview gotchas
Context
Interviewers test your knowledge of the Service Worker update cycle and multi-tab versioning safety.
The mechanical answer
To prevent breaking running applications when different tabs share state, the browser installs the new Service Worker in the background and places it into the **waiting** state. The new worker will not take control until *all* tabs controlled by the old worker are completely closed. To force immediate takeover, call `self.skipWaiting()` in the `install` handler and `self.clients.claim()` in the `activate` handler.
Trap
Refreshing a single tab does not necessarily activate the waiting worker if other tabs with the same origin remain open.
Context
This tests separation of concerns in browser caching architectures.
The mechanical answer
The HTTP Browser Cache is an automatic, declarative, disk-based cache governed by server response headers (`Cache-Control`, `ETag`, `Expires`). `CacheStorage` is a fully programmatic, JavaScript-accessible key-value database that stores raw `Request` / `Response` pairs, granting developers complete control over cache insertion, matching, eviction, and offline mocking.
Trap
Calling `caches.match()` does not read from the HTTP disk cache; it queries the explicit `CacheStorage` API.