Files
PinchChat/public/sw.js
Nicolas Varrot 72e9bce4c5 fix: bust service worker cache on each build with version+timestamp
The SW cache name was hardcoded to 'pinchchat-v1', meaning PWA users
would get stale cached assets forever. Now the cache name includes
the package version and build timestamp, so each build creates a new
cache and old ones are cleaned up on activation.

Also adds:
- Periodic SW update check (every 30 min)
- Auto-reload when new SW version is detected
2026-02-13 11:57:32 +00:00

63 lines
2.0 KiB
JavaScript

// PinchChat Service Worker — cache static assets for offline/instant load
const CACHE_NAME = 'pinchchat-__SW_VERSION__';
// Cache static assets on install
self.addEventListener('install', (event) => {
self.skipWaiting();
});
// Clean old caches on activate
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) =>
Promise.all(keys.filter((k) => k !== CACHE_NAME).map((k) => caches.delete(k)))
)
);
self.clients.claim();
});
// Stale-while-revalidate for static assets, network-first for API/WS
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
// Skip non-GET, WebSocket upgrades, and chrome-extension requests
if (event.request.method !== 'GET') return;
if (url.protocol === 'chrome-extension:') return;
// Don't cache API calls or WebSocket-related requests
if (url.pathname.startsWith('/api') || url.pathname.startsWith('/ws')) return;
// For navigation requests (HTML), always go network-first to get latest SPA shell
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request)
.then((response) => {
const clone = response.clone();
caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone));
return response;
})
.catch(() => caches.match(event.request))
);
return;
}
// Static assets (JS, CSS, images, fonts): stale-while-revalidate
if (
url.pathname.match(/\.(js|css|png|jpg|jpeg|gif|webp|svg|woff2?|ttf|ico|json)$/) ||
url.pathname.startsWith('/assets/')
) {
event.respondWith(
caches.open(CACHE_NAME).then((cache) =>
cache.match(event.request).then((cached) => {
const fetchPromise = fetch(event.request).then((response) => {
if (response.ok) cache.put(event.request, response.clone());
return response;
});
return cached || fetchPromise;
})
)
);
return;
}
});