Debugging service workers
In one line: The Application panel in Chrome DevTools (and equivalent panels in Firefox and Safari) lets you inspect the registration state, force updates, test offline, clear caches, and observe fetch event interception — all without deploying a change.
Chrome DevTools
Section titled “Chrome DevTools”Application → Service Workers
Section titled “Application → Service Workers”The primary debugging surface. Open DevTools → Application → Service Workers (left sidebar).
| Control | What it does |
|---|---|
| Update on reload | Forces a byte-comparison check and installs a new worker every navigation |
| Bypass for network | Disables the service worker for this tab — all fetch events pass through |
| Offline | Simulates no network for requests going through the service worker |
| Update | Triggers registration.update() manually |
| Unregister | Removes the registration entirely |
The panel also shows the current state: installing, waiting, or activated — plus the script URL and scope.
Forcing a worker update
Section titled “Forcing a worker update”The “Update on reload” checkbox is the fastest way to test worker changes in development. Without it, Chrome serves the cached worker script for up to 24 hours even if the file changes, and the browser only installs a new worker when it detects a byte difference.
If a new worker is stuck in waiting, the panel shows a “skipWaiting” link that calls skipWaiting() immediately for the pending worker — useful for testing without modifying the worker code.
Cache Storage
Section titled “Cache Storage”DevTools → Application → Cache Storage lists all named caches and their entries. You can inspect request/response headers, preview response bodies, and delete individual entries or entire caches.
Inspecting fetch events
Section titled “Inspecting fetch events”Open the Network panel and enable the Service Worker column (right-click on column headers). Each request shows whether it was served from the service worker, from cache, or from the network. The (ServiceWorker) label in the “Size” column confirms the worker intercepted the request.
Console in the worker context
Section titled “Console in the worker context”Switch the DevTools console’s JavaScript context (the dropdown next to the filter bar) from “top” to the service worker URL. console.log calls inside the worker appear in this context.
You can also evaluate expressions against the worker’s global scope, including inspecting self.registration, caches.keys(), and self.clients.matchAll().
Firefox DevTools
Section titled “Firefox DevTools”Open about:debugging#/runtime/this-firefox → “This Firefox” → “Service Workers”. Firefox lists every registered worker with its scope, state, and a Inspect link that opens a dedicated console for that worker.
Firefox does not have a built-in “Update on reload” checkbox. To force a re-install during development, unregister the worker and reload, or call registration.update() in the page console.
Safari Web Inspector
Section titled “Safari Web Inspector”In Safari (iOS or macOS), enable the Develop menu (Preferences → Advanced → Show Develop menu). Open Web Inspector → Storage → Service Workers. Safari lists registered workers, their scopes, and the script URL.
Safari Web Inspector has more limited debugging surfaces than Chrome or Firefox: there is no dedicated cache viewer or “force update” checkbox. Use the console in the worker context for caches.keys() inspection.
Diagnosing common problems
Section titled “Diagnosing common problems”| Symptom | Likely cause | Fix |
|---|---|---|
| Worker stuck in waiting | Old tabs still open and no skipWaiting() |
Close all tabs, or use DevTools “skipWaiting” link |
| New code not running after deploy | HTTP cache serving the old worker script | Use updateViaCache: 'none' or set Cache-Control: no-cache on the worker URL |
| Requests not intercepted | Worker not yet activated (still installing) or scope mismatch | Check scope in DevTools; reload after activation |
| Cache not populated | install failed or event.waitUntil() was not called |
Check the console in the worker context for errors |
| Stale content served | CacheFirst strategy with no expiration |
Add ExpirationPlugin or version your cache name |
| Offline fallback not shown | Fallback not pre-cached in install, or wrong fetch event guard |
Check Cache Storage for the fallback URL; add logging |
Workbox logging
Section titled “Workbox logging”Workbox emits verbose logs in development builds. When using Workbox, switch to the development build during debugging:
import { setCacheNameDetails } from 'workbox-core';// Development builds log strategy decisions to the consoleWorkbox’s development build is automatically selected when process.env.NODE_ENV !== 'production'.
Practical checklist
Section titled “Practical checklist”- Enable “Update on reload” in DevTools during development to avoid cached-worker confusion.
- Open the worker console context to see worker-side
console.logoutput. - Use “Bypass for network” when you want to test behavior without the service worker temporarily.
- After a deploy, verify Cache Storage contains only the new cache version and old caches are deleted.
- Test the offline fallback by checking “Offline” in DevTools Network and navigating to an uncached URL.
Cross-references
Section titled “Cross-references”- The update flow and skipWaiting — understanding why workers get stuck in waiting
- Caching strategies — the strategies visible in Cache Storage
- Registration and scope — scope issues visible in the Service Workers panel