Files
fotospiel-app/public/guest-sw.js

70 lines
2.0 KiB
JavaScript

// Minimal service worker for Guest PWA queue sync
self.addEventListener('install', (event) => {
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim());
});
const ASSETS_CACHE = 'guest-assets-v1';
const IMAGES_CACHE = 'guest-images-v1';
self.addEventListener('fetch', (event) => {
const req = event.request;
if (req.method !== 'GET') return;
const url = new URL(req.url);
// Only handle same-origin requests
if (url.origin !== self.location.origin) return;
// Never cache API calls; let them hit network directly
if (url.pathname.startsWith('/api/')) return;
// Cache-first for images
if (req.destination === 'image' || /\.(png|jpg|jpeg|webp|avif|gif|svg)(\?.*)?$/i.test(url.pathname)) {
event.respondWith((async () => {
const cache = await caches.open(IMAGES_CACHE);
const cached = await cache.match(req);
if (cached) return cached;
try {
const res = await fetch(req, { credentials: 'same-origin' });
if (res.ok) cache.put(req, res.clone());
return res;
} catch (e) {
return cached || Response.error();
}
})());
return;
}
// Stale-while-revalidate for CSS/JS assets
if (req.destination === 'style' || req.destination === 'script') {
event.respondWith((async () => {
const cache = await caches.open(ASSETS_CACHE);
const cached = await cache.match(req);
const networkPromise = fetch(req, { credentials: 'same-origin' })
.then((res) => {
if (res.ok) cache.put(req, res.clone());
return res;
})
.catch(() => null);
return cached || (await networkPromise) || Response.error();
})());
return;
}
});
self.addEventListener('sync', (event) => {
if (event.tag === 'upload-queue') {
event.waitUntil(
(async () => {
const clients = await self.clients.matchAll({ includeUncontrolled: true, type: 'window' });
for (const client of clients) {
client.postMessage({ type: 'sync-queue' });
}
})()
);
}
});