From e95188c32a2c85bf8f39294f745238b09030ff23 Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Wed, 12 Feb 2025 22:08:35 +0100 Subject: [PATCH] fix: sw offline app --- public/sw.js | 89 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 20 deletions(-) diff --git a/public/sw.js b/public/sw.js index 6ada58b..7c68057 100644 --- a/public/sw.js +++ b/public/sw.js @@ -32,27 +32,76 @@ self.addEventListener("activate", (event) => { self.clients.claim(); }); -// Stratégie de cache : Network First avec fallback sur le cache +// Stratégie de cache différente selon le type de requête self.addEventListener("fetch", (event) => { - // Ne pas intercepter les requêtes vers l'API + // Pour les requêtes API, on utilise "Network First" avec un timeout if (event.request.url.includes("/api/")) { - return; + event.respondWith( + Promise.race([ + fetch(event.request.clone()) + .then((response) => { + // Ne mettre en cache que les réponses réussies + if (response.ok) { + const responseToCache = response.clone(); + caches.open(CACHE_NAME).then((cache) => { + cache.put(event.request, responseToCache); + }); + } + return response; + }) + .catch(() => { + // En cas d'erreur réseau, essayer le cache + return caches.match(event.request).then((cachedResponse) => { + if (cachedResponse) { + return cachedResponse; + } + // Si pas de cache, renvoyer une erreur appropriée + return new Response(JSON.stringify({ error: "Hors ligne" }), { + status: 503, + headers: { "Content-Type": "application/json" }, + }); + }); + }), + // Timeout après 5 secondes + new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout")), 5000)).catch( + () => { + return caches.match(event.request).then((cachedResponse) => { + if (cachedResponse) { + return cachedResponse; + } + return new Response(JSON.stringify({ error: "Timeout" }), { + status: 504, + headers: { "Content-Type": "application/json" }, + }); + }); + } + ), + ]) + ); + } else { + // Pour les autres ressources, on garde la stratégie "Cache First" + event.respondWith( + caches.match(event.request).then((cachedResponse) => { + if (cachedResponse) { + return cachedResponse; + } + return fetch(event.request) + .then((response) => { + // Mettre en cache la nouvelle réponse + const responseToCache = response.clone(); + caches.open(CACHE_NAME).then((cache) => { + cache.put(event.request, responseToCache); + }); + return response; + }) + .catch(() => { + // Si la requête échoue et que c'est une page, renvoyer la page hors ligne + if (event.request.mode === "navigate") { + return caches.match(OFFLINE_PAGE); + } + return new Response("Hors ligne", { status: 503 }); + }); + }) + ); } - - event.respondWith( - fetch(event.request) - .then((response) => { - // Mettre en cache la nouvelle réponse - const responseClone = response.clone(); - caches.open(CACHE_NAME).then((cache) => { - cache.put(event.request, responseClone); - }); - return response; - }) - .catch(async () => { - const cache = await caches.open(CACHE_NAME); - const cachedResponse = await cache.match(event.request); - return cachedResponse || cache.match(OFFLINE_PAGE); - }) - ); });