From 31283ada267b2e63c109afd23fabbbff011903b6 Mon Sep 17 00:00:00 2001 From: gilles Date: Tue, 22 Sep 2026 10:04:47 +0200 Subject: [PATCH] =?UTF-8?q?feat(pwa):=20hors-ligne=20(app=20shell=20+=20le?= =?UTF-8?q?cture=20API)=20et=20suppression=20depuis=20la=20page=20d'=C3=A9?= =?UTF-8?q?dition?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - sw.ts : API GET, navigation et payloads RSC en network-first (cache en secours hors-ligne) ; écritures non interceptées ; fallback ~offline - edit page : bouton Supprimer avec confirmation (CardDeleteButton) --- src/app/cards/[id]/edit/page.tsx | 6 +++++- src/app/sw.ts | 35 +++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/app/cards/[id]/edit/page.tsx b/src/app/cards/[id]/edit/page.tsx index da374ea..2f84deb 100644 --- a/src/app/cards/[id]/edit/page.tsx +++ b/src/app/cards/[id]/edit/page.tsx @@ -1,6 +1,7 @@ import type { Metadata } from 'next' import Link from 'next/link' import { notFound } from 'next/navigation' +import { CardDeleteButton } from '@/components/card-delete' import { CardForm } from '@/components/card-form' import type { Card, CardInput } from '@/domain/card' import { ApiClientError, cardsApi } from '@/lib/api-client' @@ -33,7 +34,10 @@ export default async function EditCardPage({ params }: { params: Promise<{ id: s > ← Retour au détail -

{card.question}

+
+

{card.question}

+ +
diff --git a/src/app/sw.ts b/src/app/sw.ts index 00c7d7a..c0bb34a 100644 --- a/src/app/sw.ts +++ b/src/app/sw.ts @@ -1,7 +1,7 @@ /// import { defaultCache } from '@serwist/turbopack/worker' import type { PrecacheEntry, RuntimeCaching, SerwistGlobalConfig } from 'serwist' -import { NetworkOnly, Serwist } from 'serwist' +import { ExpirationPlugin, NetworkFirst, Serwist } from 'serwist' declare global { interface WorkerGlobalScope extends SerwistGlobalConfig { @@ -11,11 +11,40 @@ declare global { declare const self: ServiceWorkerGlobalScope -// Ne jamais mettre en cache les appels API +// API : lectures (GET) en réseau d'abord, servies depuis le cache en secours +// hors-ligne. Les écritures (POST/PUT/DELETE) ne sont pas interceptées par le +// service worker et passent toujours par le réseau. const runtimeCaching: RuntimeCaching[] = [ { matcher: ({ sameOrigin, url }) => sameOrigin && url.pathname.startsWith('/api/'), - handler: new NetworkOnly(), + handler: new NetworkFirst({ + networkTimeoutSeconds: 3, + cacheName: 'api-network-first', + plugins: [ + new ExpirationPlugin({ + maxEntries: 200, + maxAgeSeconds: 7 * 24 * 60 * 60, + }), + ], + }), + }, + // Navigation : réseau d'abord (pages toujours fraîches après déploiement), + // cache en secours uniquement hors-ligne + { + matcher: ({ request }) => request.mode === 'navigate', + handler: new NetworkFirst({ + networkTimeoutSeconds: 3, + cacheName: 'pages-network-first', + }), + }, + // Payloads RSC des navigations côté client : réseau d'abord + { + matcher: ({ request, sameOrigin }) => + sameOrigin && request.headers.get('rsc') === '1', + handler: new NetworkFirst({ + networkTimeoutSeconds: 3, + cacheName: 'rsc-network-first', + }), }, ...defaultCache, ]