// sw.js
const CACHE_NAME = 'my-cache'; // never changes!
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME).then(cache =>
cache.addAll(['/index.html', '/app.js', '/styles.css'])
)
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(cached =>
cached || fetch(event.request)
)
);
});
// No activate handler — old caches never cleaned up!// sw.js
const VERSION = 'v2'; // increment on each deploy!
const CACHE_NAME = `my-cache-${VERSION}`;
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME).then(cache =>
cache.addAll(['/index.html', '/app.js', '/styles.css'])
).then(() => self.skipWaiting()) // activate immediately
);
});
// Delete old caches on activation
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys()
.then(keys => keys.filter(key => key !== CACHE_NAME))
.then(oldKeys => Promise.all(oldKeys.map(key => caches.delete(key))))
.then(() => self.clients.claim()) // take control of open pages
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(cached => cached || fetch(event.request))
);
});Bug: CACHE_NAME never changes so the install event finds the existing cache — no update. No activate handler means old service workers keep serving stale assets.
Explanation: Version the cache name — new SW gets a new cache. activate handler deletes old caches. skipWaiting + clients.claim ensure the new SW takes over immediately.
Key Insight: Service worker caching: version your cache name, clean old caches in activate, call skipWaiting() in install and clients.claim() in activate for immediate takeover.