diff --git a/public/sw.js b/public/sw.js new file mode 100644 index 0000000..f717f50 --- /dev/null +++ b/public/sw.js @@ -0,0 +1,53 @@ +const CACHE_NAME = "agendamax-shell-v1"; +const SHELL_URLS = ["/", "/manifest.webmanifest", "/favicon.svg", "/icon-192.png", "/icon-512.png"]; + +self.addEventListener("install", (event) => { + event.waitUntil( + caches.open(CACHE_NAME).then((cache) => cache.addAll(SHELL_URLS)).then(() => self.skipWaiting()) + ); +}); + +self.addEventListener("activate", (event) => { + event.waitUntil( + caches.keys() + .then((keys) => Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key)))) + .then(() => self.clients.claim()) + ); +}); + +self.addEventListener("fetch", (event) => { + const { request } = event; + const url = new URL(request.url); + if (request.method !== "GET" || url.origin !== self.location.origin || url.pathname.startsWith("/api/")) return; + + if (request.mode === "navigate") { + event.respondWith( + fetch(request) + .then((response) => { + if (response.ok) { + const copy = response.clone(); + void caches.open(CACHE_NAME).then((cache) => cache.put(request, copy)); + } + return response; + }) + .catch(() => caches.match("/")) + ); + return; + } + + const cacheableDestination = new Set(["script", "style", "image", "font", "manifest", "worker"]); + if (!cacheableDestination.has(request.destination)) return; + + event.respondWith( + caches.match(request).then((cached) => { + if (cached) return cached; + return fetch(request).then((response) => { + if (response.ok) { + const copy = response.clone(); + void caches.open(CACHE_NAME).then((cache) => cache.put(request, copy)); + } + return response; + }); + }) + ); +}); diff --git a/src/main.tsx b/src/main.tsx index 33d9969..bc3b336 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -24,3 +24,13 @@ createRoot(document.getElementById("root")!).render( ); + +if (import.meta.env.PROD && "serviceWorker" in navigator) { + window.addEventListener("load", () => { + void navigator.serviceWorker + .register("/sw.js", { updateViaCache: "none" }) + .catch((error: unknown) => { + if (import.meta.env.DEV) console.warn("AgendaMax service worker registration failed", error); + }); + }); +}