Service Workers and PWAs

A service worker is a background script that the browser runs separately from your web page, acting as a programmable network proxy that can cache responses and serve your app offline — the foundation of Progressive Web Apps (PWAs).

Learn Service Workers and PWAs in our free JavaScript course — an interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

💡 Running Code Locally: Service workers require a secure context and a real server. The snippets below are illustrative. For the best experience:

📮 Real-World Analogy: A service worker is like a helpful mailroom clerk for your app:

Service workers are the engine behind Progressive Web Apps: web apps that load fast, work offline, and can be installed to the home screen like native apps. A service worker runs in its own thread, has no access to the DOM, and stays event-driven — the browser wakes it to handle events like install , activate , and fetch , then lets it sleep. Because it can intercept every network request, it must be served over HTTPS .

🔥 Registering a Service Worker

From your page, register the worker with navigator.serviceWorker.register() . Always feature-detect first, and register after load so it does not compete with critical page resources.

The returned registration's scope tells you which pages this worker controls — by default, the folder the script lives in and everything beneath it.

🔥 The Install Event: Pre-Caching

Inside the worker ( sw.js ), the install event is where you open a cache and store the core files. Wrap async work in event.waitUntil() so the browser knows installation is not finished until caching completes.

cache.addAll() fetches and stores every URL in the array. If any request fails, installation fails — so keep the pre-cache list to essential, reliable assets.

🔥 The Activate Event: Cleaning Old Caches

When a new worker activates, old caches from previous versions should be deleted. The activate event is the right place, because the previous worker is no longer in control.

Bumping the cache name (for example to app-shell-v2 ) on each release lets the activate handler automatically purge stale assets.

🔥 The Fetch Event and Cache API

The fetch event lets the worker intercept requests. With event.respondWith() you decide the response — often by checking the cache first via caches.match() .

Cache-first is great for static assets that rarely change. It returns instantly from storage and only touches the network on a miss.

🔥 Network-First with Offline Fallback

For content that should be fresh (like API data or HTML), use network-first : try the network, and fall back to the cache (or an offline page) when the request fails.

Note the response.clone() : a response body can only be read once, so you clone it to both return it and store it. This pattern keeps users online-fresh but offline-capable.

🔥 The Web App Manifest and Installability

A PWA becomes installable when you provide a web app manifest — a JSON file describing the app — and link it from your HTML. Combined with a service worker over HTTPS, browsers offer an "Install" prompt.

Key fields: name / short_name , a start_url , a display mode like standalone , and appropriately sized icons (at least 192px and 512px). Installed PWAs launch in their own window without browser chrome.

🔥 Scope and the HTTPS Requirement

A worker registered at /app/sw.js controls only /app/ and below. You can narrow scope with the scope option, but you cannot widen it beyond the script's directory. And because the worker can rewrite traffic, the origin must be secure .

HTTPS prevents man-in-the-middle attackers from hijacking the proxy. localhost is exempt so you can develop without a certificate.

🔥 Service Workers vs Web Workers

Both run off the main thread and cannot touch the DOM, but they solve different problems. A Web Worker offloads CPU-heavy work for a single page. A service worker is a persistent, event-driven network proxy shared across all pages in its scope.

🔥 Common Service Worker Mistakes to Avoid

❌ Anti-Patterns

🎯 Key Takeaways

Practice quiz

What is a service worker?

  • A script the browser runs in the background, separate from the page, acting as a network proxy
  • A type of database
  • A server-side rendering engine
  • A CSS preprocessor

Answer: A script the browser runs in the background, separate from the page, acting as a network proxy. A service worker is a background script that runs separately from the web page and can intercept network requests, acting as a programmable proxy.

Which API registers a service worker?

  • document.registerSW()
  • serviceWorker.start()
  • navigator.serviceWorker.register()
  • window.installWorker()

Answer: navigator.serviceWorker.register(). You register a service worker by calling navigator.serviceWorker.register('/sw.js'), usually after the page loads.

What is the correct order of the core service worker lifecycle events?

  • activate, install, fetch
  • install, activate, fetch
  • fetch, activate, install
  • fetch, install, activate

Answer: install, activate, fetch. A service worker first installs (good for pre-caching), then activates (good for cleaning old caches), then handles fetch events.

During which event do you typically pre-cache the app shell?

  • The fetch event
  • The message event
  • The activate event
  • The install event

Answer: The install event. The install event is the ideal place to open a cache and pre-cache the core app shell with event.waitUntil().

Which method looks for a matching cached response?

  • caches.match()
  • storage.lookup()
  • cache.find()
  • fetch.cached()

Answer: caches.match(). caches.match(request) searches the Cache Storage for a response that matches the request and returns it if found.

What does a 'cache-first' strategy do?

  • It only ever uses the network
  • It serves from cache if available, falling back to the network
  • It deletes the cache on every request
  • It always ignores the cache

Answer: It serves from cache if available, falling back to the network. Cache-first returns a cached response immediately when present and only goes to the network on a cache miss, enabling fast offline-capable loads.

What makes a Progressive Web App installable?

  • A large image file
  • A single HTML file with no JavaScript
  • Disabling the cache
  • A valid web app manifest plus a registered service worker served over HTTPS

Answer: A valid web app manifest plus a registered service worker served over HTTPS. Installability requires a web app manifest (name, icons, start_url, display), a service worker, and a secure (HTTPS) origin.

What security requirement do service workers have?

  • They only work in incognito mode
  • They must be inline in the HTML
  • They must be served over HTTPS (localhost is exempt for development)
  • They require a paid certificate from the browser vendor

Answer: They must be served over HTTPS (localhost is exempt for development). Because they can intercept network traffic, service workers require a secure context (HTTPS), with localhost allowed for development.

What does a service worker's scope control?

  • The size of the cache only
  • Which URLs/pages the service worker can control and intercept
  • The number of tabs allowed
  • The colors of the page

Answer: Which URLs/pages the service worker can control and intercept. Scope defines the set of pages a service worker controls; by default it is the directory of the script and cannot be broader than that path.

How does a service worker differ from a regular Web Worker?

  • A service worker is event-driven, persists across page loads, and can intercept network requests, while a Web Worker runs tied to a page for CPU work
  • They are identical
  • A Web Worker can intercept network requests but a service worker cannot
  • A service worker can directly manipulate the DOM

Answer: A service worker is event-driven, persists across page loads, and can intercept network requests, while a Web Worker runs tied to a page for CPU work. A Web Worker offloads CPU work for a single page; a service worker is a persistent, event-driven network proxy shared across pages. Neither can touch the DOM directly.