# PWA (Progressive Web App) Documentation [Vite-PWA](https://vite-pwa-org.netlify.app/) Une **Progressive Web App (PWA)** est une application qui combine le meilleur du web et du mobile. Elle s'installe sur l'écran d'accueil, fonctionne hors connexion et offre une expérience fluide proche d'une app native. ## Configuration Vite ### Configuration complète ``` // vite.config.js import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import tailwindcss from "@tailwindcss/vite"; import { VitePWA } from "vite-plugin-pwa"; import path from "path"; export default defineConfig(({ mode }) => { const isDev = mode === 'development'; return { appType: 'spa', build: isDev ? { minify: false, sourcemap: true, } : { minify: 'terser', terserOptions: { compress: { drop_console: true, drop_debugger: true }, }, sourcemap: false, }, optimizeDeps: { include: ['prop-types', 'parse-numeric-range', 'boolbase', 'style-to-object', 'debug', 'extend', 'react-signature-canvas'], }, resolve: { alias: { 'src': path.resolve(__dirname, './src'), 'prop-types': 'prop-types/prop-types.js', }, }, plugins: [ react(), tailwindcss(), VitePWA({ registerType: 'autoUpdate', workbox: { globPatterns: ['**/*.{js,css,html,ico,png,svg,json}'], cleanupOutdatedCaches: true, maximumFileSizeToCacheInBytes: 3000000, skipWaiting: true, clientsClaim: true, runtimeCaching: [ { urlPattern: /\/api\/(home|profile)/, handler: 'NetworkFirst', options: { cacheName: 'api-cache', expiration: { maxEntries: 50, maxAgeSeconds: 60 * 60 * 24 * 7, }, cacheableResponse: { statuses: [0, 200] }, networkTimeoutSeconds: 10, }, }, { urlPattern: /\.(?:png|jpg|jpeg|svg|gif|webp)$/, handler: 'CacheFirst', options: { cacheName: 'images-cache', expiration: { maxEntries: 100, maxAgeSeconds: 60 * 60 * 24 * 30, }, }, }, ], }, injectRegister: "auto", includeAssets: ["favicon.ico", "assets/*", "favicon.png", "apple-touch-icon.png"], // Dynamic manifest served by SmartAuth PwaController manifest: false, }), ] }; }); ``` ### Points clés de la configuration - **Build conditionnel** : sourcemaps et logs en dev, minification et suppression des console.log en production - **Runtime caching** : les routes API ''/api/home'' et ''/api/profile'' sont cachées en NetworkFirst, les images en CacheFirst - **manifest: false** : le manifest n'est pas généré par Vite, il est servi dynamiquement par SmartAuth (voir ci-dessous) ## Manifest dynamique (SmartAuth) SmartBoot utilise un **manifest dynamique** servi par SmartAuth via le ''PwaController''. Le manifest est généré à partir des constantes Dolibarr de votre module. ### Configuration dans index.html ```
``` ### Routes SmartAuth ^ Route ^ Description ^ | GET ''/manifest'' | Retourne le manifest.json dynamique | | GET ''/icon/{size}'' | Retourne l'icône PWA à la taille demandée (64, 192, 512) | ### Constantes Dolibarr Configurez le manifest via les constantes de votre module dans l'administration Dolibarr : ^ Constante ^ Description ^ Défaut ^ | ''{MODULE}_PWA_NAME'' | Nom complet de l'application | Nom du module | | ''{MODULE}_PWA_SHORT_NAME'' | Nom court (sous l'icône) | Nom du module | | ''{MODULE}_PWA_DESCRIPTION'' | Description | - | | ''{MODULE}_PWA_THEME_COLOR'' | Couleur du thème | ''#5fbabf'' | | ''{MODULE}_PWA_BACKGROUND_COLOR'' | Couleur de fond | ''#ffffff'' | ### Icônes Le PwaController cherche les icônes dans cet ordre : - Upload personnalisé dans l'administration du module - Icône par défaut du module - Placeholder généré par GD (si disponible) Les tailles disponibles sont 64x64, 192x192 et 512x512. ## Service Worker et Cache ### Stratégies de cache Workbox La configuration des stratégies de cache se fait dans la section ''runtimeCaching'' de la config Vite (voir ci-dessus). ### Stratégies disponibles ^ Stratégie ^ Usage ^ | ''CacheFirst'' | Assets statiques (fonts, images) | | ''NetworkFirst'' | API, données dynamiques | | ''StaleWhileRevalidate'' | Contenu qui peut être légèrement obsolète | | ''NetworkOnly'' | Toujours réseau (authentification) | | ''CacheOnly'' | Uniquement cache (assets embarqués) | ## Mise à jour de l'application SmartCommon fournit le hook ''usePWAUpdate'' et le composant ''UpdatePrompt'' pour gérer les mises à jour du Service Worker. ### usePWAUpdate Hook pour détecter et appliquer les mises à jour PWA. ``` import { usePWAUpdate } from '@cap-rel/smartcommon'; const MyApp = () => { const { updateAvailable, // true quand une mise à jour est prête updateActivated, // true quand la mise à jour est activée checkForUpdates, // vérification manuelle applyUpdate, // appliquer la mise à jour (skip waiting + reload) reloadPage, // recharger la page } = usePWAUpdate({ autoReload: false, // recharger automatiquement (défaut: false) checkInterval: 0, // intervalle de vérification en ms (0 = désactivé) onUpdateAvailable: () => {}, // callback quand une MAJ est disponible onUpdateActivated: () => {}, // callback quand la MAJ est activée }); return (
{updateAvailable && ( )}
); }; ``` ### UpdatePrompt Composant prêt à l'emploi qui affiche une notification de mise à jour. Trois variantes disponibles : ^ Variante ^ Description ^ | ''toast'' | Notification toast en bas de l'écran (défaut) | | ''banner'' | Bandeau fixe en haut ou en bas | | ''modal'' | Fenêtre modale centrée | ``` import { UpdatePrompt } from '@cap-rel/smartcommon'; const App = () => ( ); ``` ## Mode Offline ### Détecter la connexion SmartCommon fournit le hook ''useOnlineStatus'' qui détecte l'état de la connexion avec support optionnel de health check serveur : ``` import { useOnlineStatus } from '@cap-rel/smartcommon'; const MyComponent = () => { const { isOnline, // true si le navigateur est en ligne isServerReachable, // true/false/null selon le health check lastOnline, // timestamp de la dernière connexion checkNow, // vérification manuelle } = useOnlineStatus({ healthCheckUrl: '/api/health', // URL de health check (optionnel) healthCheckInterval: 30000, // intervalle en ms (défaut: 30000) stabilityDelay: 2000, // délai de stabilisation (défaut: 2000) timeout: 5000, // timeout du health check (défaut: 5000) }); return (
{!isOnline && (
Mode hors connexion
)}
); }; ``` ### Synchronisation offline SmartCommon fournit ''useSyncClient'' pour la synchronisation offline complète avec gestion de conflits : ``` import { useSyncClient } from '@cap-rel/smartcommon'; const sync = useSyncClient({ apiUrl: import.meta.env.VITE_API_URL, getAccessToken: () => api.user?.accessToken, scope: ['items'], autoSync: true, syncInterval: 60000, }); // CRUD offline (les opérations sont mises en file d'attente) await sync.create('items', { label: 'Nouveau' }); await sync.update('items', id, { label: 'Modifié' }); await sync.remove('items', id); // Synchroniser manuellement await sync.sync(); // push + pull // Vérifier l'état console.log(sync.pendingCount); // opérations en attente console.log(sync.isSyncing); // synchronisation en cours ``` Voir [[synchronisation|Synchronisation offline]] pour plus de détails. Pour un stockage IndexedDB simple sans synchronisation serveur, vous pouvez aussi utiliser ''useDb'' (voir [[stockage_de_donnees|Stockage de données]]). ## Build et déploiement ### Commandes ``` # Build de production npm run build # Prévisualiser le build npm run preview # Le build génère: # - dist/index.html # - dist/assets/*.js # - dist/assets/*.css # - dist/sw.js (Service Worker) ``` ### Vérification Après le build, vérifiez dans les DevTools : * **Application > Manifest** : Le manifest est chargé * **Application > Service Workers** : Le SW est actif * **Application > Storage > Cache Storage** : Les assets sont cachés ### Déployer sur Dolibarr Copiez le contenu de ''dist/'' dans le dossier ''pwa/'' de votre module Dolibarr : ``` # Depuis le dossier mobile/ npm run build cp -r dist/* ../pwa/ ``` Ou utilisez le Makefile fourni par SmartBoot : ``` make pwa ``` ## Tester la PWA ### Lighthouse 1. Ouvrez les DevTools (F12) 2. Allez dans l'onglet "Lighthouse" 3. Sélectionnez "Progressive Web App" 4. Lancez l'audit ### Critères de validation * HTTPS (ou localhost en dev) * Manifest valide avec icônes * Service Worker enregistré * Fonctionne hors connexion * Responsive design ## Voir aussi * [[configuration|Configuration]] - Configuration Vite complète * [[stockage_de_donnees|Stockage de données]] - IndexedDB pour le offline * [Vite-PWA](https://vite-pwa-org.netlify.app/) - Documentation officielle