PWA — Progressive Web App¶
Primatch est une Progressive Web App installable sur mobile et desktop, offrant une expérience proche d'une application native.
Vue d'ensemble¶
| Élément | Valeur |
|---|---|
| Plugin | vite-plugin-pwa v1.x (Workbox) |
| Mode | generateSW (service worker auto-généré) |
| Register type | prompt (l'utilisateur choisit quand mettre à jour) |
| Fichier manifest | dist/manifest.webmanifest |
| Service worker | dist/sw.js |
Manifest¶
Le manifest est configuré directement dans vite.config.ts via le plugin VitePWA :
manifest: {
name: 'Primatch — Padel entre amis',
short_name: 'Primatch',
description: 'Trouvez des partenaires de padel et organisez vos parties.',
theme_color: '#00C2C2',
background_color: '#F7F8FC',
display: 'standalone',
orientation: 'portrait',
scope: '/',
start_url: '/',
icons: [
{ src: '/icon-192.svg', sizes: '192x192', type: 'image/svg+xml' },
{ src: '/icon-512.svg', sizes: '512x512', type: 'image/svg+xml' },
{ src: '/icon-maskable-512.svg', sizes: '512x512', type: 'image/svg+xml', purpose: 'maskable' },
],
}
Icônes¶
Les icônes au format SVG sont dans frontend/public/ :
| Fichier | Taille | Usage |
|---|---|---|
favicon.svg | 32×32 | Onglet navigateur |
apple-touch-icon.svg | 180×180 | iOS « Ajouter à l'écran d'accueil » |
icon-192.svg | 192×192 | Manifest (Android) |
icon-512.svg | 512×512 | Manifest / splash screen |
icon-maskable-512.svg | 512×512 | Adaptive icon (Android, zone de sécurité) |
Service Worker (Workbox)¶
Stratégie de pré-cache¶
Tous les assets statiques sont pré-cachés automatiquement au build :
Le build génère environ 15 entrées de pré-cache (~630 Ko).
Cache runtime¶
Les requêtes vers les Google Fonts sont cachées en runtime avec une stratégie CacheFirst :
runtimeCaching: [
{
urlPattern: /^https:\/\/fonts\.googleapis\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'google-fonts-cache',
expiration: { maxEntries: 10, maxAgeSeconds: 60 * 60 * 24 * 365 },
cacheableResponse: { statuses: [0, 200] },
},
},
{
urlPattern: /^https:\/\/fonts\.gstatic\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'gstatic-fonts-cache',
expiration: { maxEntries: 10, maxAgeSeconds: 60 * 60 * 24 * 365 },
cacheableResponse: { statuses: [0, 200] },
},
},
]
Requêtes API
Les appels API (/api/v1/…) ne sont pas cachés par le service worker. La gestion du cache API est déléguée à React Query côté client.
Mise à jour automatique¶
Le service worker est enregistré avec registerType: 'prompt' :
- Vérification horaire — un
setIntervalde 1 h appelleregistration.update()pour détecter les nouvelles versions. - Bannière de mise à jour — quand
needRefreshdevienttrue, un composantPWAUpdatePrompts'affiche en bas de l'écran. - Action utilisateur — le joueur peut cliquer sur « Mettre à jour » pour activer le nouveau service worker, ou « Plus tard » pour ignorer.
┌────────────────────────────────────────────┐
│ 🔄 Mise à jour disponible │
│ Une nouvelle version est prête. │
│ [ Plus tard ] [ MAJ ] │
└────────────────────────────────────────────┘
Invite d'installation¶
L'application intercepte l'événement beforeinstallprompt du navigateur :
- L'événement est différé et stocké dans un state React.
- Une bannière invite l'utilisateur à installer l'application.
- Au clic sur « Installer »,
deferredPrompt.prompt()est appelé. - La bannière disparaît après la décision de l'utilisateur.
Priorité
Si une mise à jour ET une invitation d'installation sont disponibles simultanément, la mise à jour est affichée en priorité.
Composant PWAUpdatePrompt¶
Le composant se trouve dans src/components/ui/PWAUpdatePrompt.tsx et est monté dans main.tsx.
Props : aucune (composant autonome).
Hooks utilisés :
useRegisterSW(devirtual:pwa-register/react)useTranslation(i18next, namespacecommon, clépwa.*)
Traductions (dans src/i18n/locales/{fr,en}/common.json) :
| Clé | FR | EN |
|---|---|---|
pwa.update_available | Mise à jour disponible | Update available |
pwa.update_message | Une nouvelle version est prête. | A new version is ready. |
pwa.update | Mettre à jour | Update |
pwa.later | Plus tard | Later |
pwa.install_title | Installer Primatch | Install Primatch |
pwa.install_message | Ajoutez l'application à votre écran d'accueil. | Add the app to your home screen. |
pwa.install | Installer | Install |
Meta tags¶
Les balises suivantes sont ajoutées dans index.html pour une compatibilité maximale :
<meta name="theme-color" content="#00C2C2" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="apple-mobile-web-app-title" content="Primatch" />
<meta name="description" content="Trouvez des partenaires de padel …" />
<link rel="icon" href="/favicon.svg" />
<link rel="apple-touch-icon" href="/apple-touch-icon.svg" />
Vérification¶
Build¶
La sortie doit contenir :
dist/manifest.webmanifest 0.57 kB
dist/sw.js …
dist/workbox-*.js …
PWA v1.x.x – mode: generateSW – precache XX entries (…)
Audit Lighthouse¶
- Ouvrir l'application déployée dans Chrome.
- DevTools → onglet Lighthouse → cocher Progressive Web App.
- Vérifier que le score PWA est vert (≥ 90).
Debugging¶
- Chrome DevTools → Application → Service Workers : vérifier l'état du SW (activé, en attente…).
- Chrome DevTools → Application → Manifest : vérifier le manifest chargé.
- Chrome DevTools → Application → Cache Storage : inspecter les caches Workbox.
Développement local¶
Le mode dev PWA est activé (devOptions: { enabled: true }) pour tester le service worker en développement. Le SW est régénéré à chaque changement.
Limitations en dev
Le cache et l'installation PWA ne fonctionnent pleinement qu'en HTTPS ou sur localhost. En mode dev, certaines fonctionnalités (notification push, installation) peuvent être limitées selon le navigateur.