Service workers are specialized JavaScript assets that act as network proxies between your web application and the server, enabling offline functionality, background processing, and push notifications. They run on a separate thread from your main application code, intercepting network requests to implement sophisticated caching strategies, background sync, and persistent offline experiences. Understanding the service worker lifecycle β registration, installation, activation β and mastering caching patterns like cache-first, network-first, and stale-while-revalidate transforms a standard website into a progressive web app (PWA) that feels instant, works offline, and rivals native applications in user experience. The key mental model: service workers are event-driven workers that wake up to handle specific events (install, activate, fetch, push, sync), then go dormant β they don't run continuously.
What This Cheat Sheet Covers
This topic spans 18 focused tables and 153 indexed concepts, 104 flashcards. Below is a complete table-by-table outline of this topic, spanning foundational concepts through advanced details.
A jump-to index of every table row in this cheat sheet.
An interactive map of every table and concept in this topic.
Table 1: Service Worker Registration and Lifecycle
Service worker registration establishes the worker's operational scope and initiates the browser's lifecycle state machine: install β waiting β activate β controlling. The lifecycle ensures that new versions of your service worker don't disrupt currently open pages, and understanding state transitions is critical for implementing smooth updates without forcing users to close tabs.
| Method/Event | Example | Description | |
|---|---|---|---|
navigator.serviceWorker .register('/sw.js', { scope: '/' }) .then(reg => console.log(reg.scope)) | β’ Registers a new service worker with the browser β’ scope defines which URLs the worker controls (defaults to the worker script's directory). | ||
self.addEventListener('install', e => { e.waitUntil(caches.open('v1') .then(cache => cache.addAll(['/'])))}) | β’ Fires once when a new worker is discovered β’ ideal for precaching critical assets before the worker activates | ||
self.addEventListener('activate', e => { e.waitUntil(clients.claim())}) | β’ Fires when the worker becomes active β’ perfect for cleanup tasks like deleting old caches and claiming existing clients | ||
self.addEventListener('fetch', e => { e.respondWith(caches.match(e.request) .then(r => r || fetch(e.request)))}) | β’ Fires on every network request within the worker's scope β’ lets you intercept and customize responses by serving from cache or network | ||
self.addEventListener('install', () => { self.skipWaiting()}) | Forces a waiting worker to activate immediately without waiting for open tabs to close, replacing the currently active worker. | ||
self.addEventListener('activate', e => { e.waitUntil(clients.claim())}) | Makes the newly activated worker immediately control all clients in its scope, rather than waiting for a page reload. | ||
registration.update() .then(() => console.log('Checked')) | β’ Manually checks for an updated service worker script β’ browser also checks automatically on navigation roughly every 24 hours | ||
registration.unregister() .then(success => console.log(success)) | β’ Unregisters the service worker β’ existing caches remain until explicitly deleted with caches.delete(). | ||
if (navigator.serviceWorker.controller) { console.log('Page is controlled')} | Returns the active service worker controlling the current page, or null if no worker is in control or after a hard refresh. | ||
navigator.serviceWorker.ready .then(reg => reg.showNotification('Hi')) | β’ Promise that resolves when a service worker is active and ready to control the page β’ useful for features requiring an active worker |