diff --git a/.gitignore b/.gitignore deleted file mode 100644 index a547bf3..0000000 --- a/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/index.html b/index.html index fa46007..ec77368 100644 --- a/index.html +++ b/index.html @@ -2,14 +2,22 @@ - + + + - + + + + Skori diff --git a/nginx.conf b/nginx.conf index 0b309c1..716d53e 100644 --- a/nginx.conf +++ b/nginx.conf @@ -5,21 +5,29 @@ server { index index.html; # Important pour les Single Page Applications (React Router) - # Si le fichier n'existe pas, on redirige vers index.html location / { try_files $uri $uri/ /index.html; } - # Mise en cache agressive pour les assets statiques - location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|webp)$ { + # Mise en cache agressive pour les assets statiques fingerprintés + location ~* \.(?:css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|webp|ico|pdf)$ { expires 6M; access_log off; add_header Cache-Control "public, max-age=15552000, immutable"; } - # Ne pas mettre en cache le service worker pour que la PWA se mette à jour + # Jamais de cache sur les fichiers pilotant les mises à jour PWA + location = /index.html { + add_header Cache-Control "no-cache, must-revalidate"; + } location = /sw.js { - expires -1; - add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; + add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0"; + } + location = /manifest.webmanifest { + add_header Cache-Control "no-cache, must-revalidate"; + types { } default_type application/manifest+json; + } + location ~* ^/workbox-.*\.js$ { + add_header Cache-Control "public, max-age=15552000, immutable"; } } diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000..597f744 Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/favicon-32.png b/public/favicon-32.png new file mode 100644 index 0000000..1915de8 Binary files /dev/null and b/public/favicon-32.png differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..00f251b Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/pwa-192x192.png b/public/pwa-192x192.png new file mode 100644 index 0000000..896b0ff Binary files /dev/null and b/public/pwa-192x192.png differ diff --git a/public/pwa-512x512.png b/public/pwa-512x512.png new file mode 100644 index 0000000..63e5340 Binary files /dev/null and b/public/pwa-512x512.png differ diff --git a/public/pwa-maskable-512x512.png b/public/pwa-maskable-512x512.png new file mode 100644 index 0000000..6b47dcb Binary files /dev/null and b/public/pwa-maskable-512x512.png differ diff --git a/vite.config.ts b/vite.config.ts index 2d6afa2..d8d86aa 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -8,15 +8,20 @@ export default defineConfig({ react(), VitePWA({ registerType: "autoUpdate", - includeAssets: ["favicon.ico", "apple-touch-icon.png", "mask-icon.svg"], + includeAssets: ["favicon.ico", "apple-touch-icon.png"], manifest: { - name: "Skori", + name: "Skori — Scores de jeux de société", short_name: "Skori", description: "Application Web de gestion des scores pour jeux de société", - theme_color: "#ffffff", - background_color: "#ffffff", + lang: "fr", + start_url: "/", + scope: "/", display: "standalone", + orientation: "portrait", + theme_color: "#0f766e", + background_color: "#ffffff", + categories: ["games", "utilities"], icons: [ { src: "pwa-192x192.png", @@ -29,13 +34,35 @@ export default defineConfig({ type: "image/png", }, { - src: "pwa-512x512.png", + src: "pwa-maskable-512x512.png", sizes: "512x512", type: "image/png", - purpose: "any maskable", + purpose: "maskable", }, ], }, + workbox: { + // Précache le shell de l'app + les logos/bannières (légers, en webp) + globPatterns: ["**/*.{js,css,html,ico,png,svg,webp,woff2}"], + // Les PDF de règles (jusqu'à 12 Mo) ne sont PAS précachés : + // ils sont mis en cache à la demande, à la première consultation. + runtimeCaching: [ + { + urlPattern: /\/games-assets\/.*\.pdf$/, + handler: "CacheFirst", + options: { + cacheName: "rules-pdf", + expiration: { + maxEntries: 10, + maxAgeSeconds: 60 * 60 * 24 * 90, // 90 jours + }, + cacheableResponse: { statuses: [0, 200] }, + }, + }, + ], + navigateFallback: "/index.html", + cleanupOutdatedCaches: true, + }, }), ], resolve: {