PWA (Progressive Web App)
Documentation Vite-PWA
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/homeet/api/profilesont 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
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="manifest" href="api.php/manifest">
<link rel="icon" type="image/png" href="api.php/icon/64">
<link rel="apple-touch-icon" href="api.php/icon/192">
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</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}PWANAME | Nom complet de l'application | Nom du module |
{MODULE}PWASHORTNAME | Couleur du thème | #5fbabf |
{MODULE}PWABACKGROUND_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 64×64, 192×192 et 512×512.
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 (
<div>
{updateAvailable && (
<button onClick={applyUpdate}>
Mettre à jour
</button>
)}
</div>
);
};
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 = () => (
<Provider config={appConfig}>
<UpdatePrompt
variant="toast"
checkInterval={60000}
labels={{
title: "Mise à jour disponible",
message: "Une nouvelle version est disponible.",
reloadButton: "Rafraîchir",
dismissButton: "Plus tard",
}}
/>
<Router />
</Provider>
);
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 (
<div>
{!isOnline && (
<div className="bg-yellow-500 text-white p-2 text-center">
Mode hors connexion
</div>
)}
</div>
);
};
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 offline pour plus de détails.
<note tip>Pour un stockage IndexedDB simple sans synchronisation serveur, vous pouvez aussi utiliser useDb (voir Stockage de données).</note>
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
- Ouvrez les DevTools (F12)
- Allez dans l'onglet “Lighthouse”
- Sélectionnez “Progressive Web App”
- 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 Vite complète
- Stockage de données - IndexedDB pour le offline
- Vite-PWA - Documentation officielle