Strategy
ONLINE
Browser
page makes
fetch()
fetch()
Service Worker
intercepts
the request
the request
Cache
has response
Network
online
// request log appears here…
install
precache shell
waiting
old SW active
activate
cleanup caches
fetch
intercept requests
Click a button above to walk through the lifecycle. The default deploy gets stuck in the waiting state — the new Service Worker won't activate until every old tab closes. This is why your updates don't apply after a deploy.
skipWaiting() + clients.claim() fixes it.
The Waiting Trap: When you deploy a new
sw.js, the browser installs it but keeps it in waiting until all tabs controlled by the old version close. A simple refresh is NOT enough — the old worker still controls the page during reload. Users can be stuck on the old version for days.
The Fix: Call
self.skipWaiting() in the install event to activate immediately, and self.clients.claim() in activate to take control of open pages without a reload. Together they create instant updates.
Cache versioning is how Service Workers invalidate stale assets. Bump
CACHE_VERSION on each deploy. The new SW creates a new cache; the activate event deletes old ones. Click Deploy to watch the old cache get cleaned up.
Critical: Never let your server cache
sw.js itself. Set Cache-Control: no-cache on that file. Otherwise the browser caches the old Service Worker and users are stuck forever with no recovery path.