Progressive Web App
Une PWA est une application web qui adopte des comportements d'application native â installation sur l'Ă©cran d'accueil, fonctionnement hors-ligne, notifications push â sans passer par un store et sans installer de runtime supplĂ©mentaire.
Définition & concept
Une Progressive Web App est un site web qui respecte un ensemble de critĂšres techniques lui permettant d'ĂȘtre installĂ© comme une application native sur n'importe quel device (PC, Mac, smartphone, tablette) â directement depuis le navigateur, sans passer par l'App Store ou Google Play.
Le terme "Progressive" signifie que l'application fonctionne pour tous les utilisateurs, quel que soit le navigateur, en offrant des fonctionnalités améliorées progressivement selon les capacités du navigateur et de l'appareil.
| CritĂšre | Site web classique | PWA | App native |
|---|---|---|---|
| Installation requise | Non | Non (optionnelle) | Oui (store) |
| Hors-ligne | Non | Oui (Service Worker) | Oui |
| AccÚs systÚme | TrÚs limité | Limité (APIs web) | Complet |
| Plateformes | Toutes | Toutes | Une par build |
| Mises à jour | Instantanées | Instantanées | Via store |
| Découverte | SEO, partage URL | SEO + install prompt | App Store seulement |
Historique & évolution
Lors du lancement de l'iPhone, Steve Jobs suggĂšre que les dĂ©veloppeurs crĂ©ent des "web apps" pour iPhone au lieu d'apps natives. L'idĂ©e est prĂ©maturĂ©e â les navigateurs mobiles ne sont pas assez puissants.
Le W3C spĂ©cifie les Service Workers â scripts qui s'exĂ©cutent en arriĂšre-plan, permettant le cache, le mode hors-ligne, et les notifications push. C'est la brique fondamentale des PWA.
Frances Berriman et Alex Russell (Google Chrome) forgent le terme "Progressive Web App" dans un article de blog. Chrome implémente les premiÚres APIs.
Google pousse les PWA dans Chrome Android et le Play Store. Twitter Lite et Pinterest PWA démontrent des gains de performance spectaculaires (jusqu'à 65% de sessions en plus).
Apple intĂšgre les Service Workers dans Safari, dĂ©bloqu les PWA sur iPhone et iPad. Support partiel â pas de notifications push sur iOS pendant 5 ans.
Google lance Project Fugu pour combler le fossé entre PWA et apps natives : accÚs au systÚme de fichiers, Bluetooth, NFC, clipboard avancé, badging⊠Des dizaines d'APIs sont standardisées.
Apple ajoute les notifications push pour les PWA installĂ©es sur iOS â 5 ans aprĂšs Android. Les PWA sur iPhone deviennent enfin viables pour les usages nĂ©cessitant des alertes.
File System Access, Web Bluetooth, WebUSB, WebNFC, Badging API, WebCodecs, WebGPU â les PWA accĂšdent Ă des fonctionnalitĂ©s de plus en plus proches des apps natives. Edge et Chrome supportent l'installation PWA sur desktop.
Les 3 piliers techniques
Une PWA repose sur trois technologies obligatoires. Sans l'une d'elles, elle ne peut pas ĂȘtre considĂ©rĂ©e comme une vraie PWA.
Connexion sécurisée obligatoire. Les Service Workers refusent de s'enregistrer sur HTTP (sauf localhost pour le développement).
Script proxy entre le navigateur et le réseau. GÚre le cache, le hors-ligne, les mises à jour en arriÚre-plan.
Fichier JSON qui dĂ©finit le nom, l'icĂŽne, les couleurs, l'orientation â permet l'installation et la prĂ©sence sur l'Ă©cran d'accueil.
Web App Manifest
Le fichier manifest.json (ou manifest.webmanifest) décrit
l'application au navigateur : comment elle s'affiche une fois installée.
{
"name": "Mon Application",
"short_name": "MonApp", // nom sur l'écran d'accueil
"description": "Description de l'app",
"start_url": "/", // page ouverte au lancement
"scope": "/",
"display": "standalone", // sans barre de navigateur
"orientation": "portrait",
"theme_color": "#7c3aed", // couleur barre de statut
"background_color": "#f0f4f8", // écran de démarrage
"icons": [
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png",
"purpose": "any maskable" } // maskable = icĂŽne adaptative Android
],
"screenshots": [ // miniatures dans le prompt d'installation
{ "src": "/screens/desktop.png", "sizes": "1280x800", "form_factor": "wide" },
{ "src": "/screens/mobile.png", "sizes": "390x844", "form_factor": "narrow" }
],
"shortcuts": [ // raccourcis depuis l'icĂŽne (appui long Android)
{ "name": "Nouveau document", "url": "/new" }
],
"share_target": { // recevoir des fichiers partagés depuis d'autres apps
"action": "/share", "method": "POST",
"enctype": "multipart/form-data",
"params": { "files": [{ "name": "fichiers", "accept": ["image/*"] }] }
}
}
<head> <link rel="manifest" href="/manifest.json"> <meta name="theme-color" content="#7c3aed"> <!-- iOS (Safari ne lit pas le manifest pour ces tags) --> <meta name="apple-mobile-web-app-capable" content="yes"> <link rel="apple-touch-icon" href="/icons/apple-touch-icon.png"> </head>
Service Worker â Cache & Offline
Le Service Worker est un script JavaScript qui s'exĂ©cute en arriĂšre-plan, sĂ©parĂ© de la page. Il intercepte toutes les requĂȘtes rĂ©seau et peut les servir depuis un cache local.
const CACHE_NAME = 'monapp-v1' const ASSETS = ['/', '/index.html', '/app.css', '/app.js', '/icons/icon-192.png'] // Installation : mise en cache des assets statiques self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME).then(cache => cache.addAll(ASSETS)) ) }) // Activation : nettoyage des anciens caches self.addEventListener('activate', event => { event.waitUntil( caches.keys().then(keys => Promise.all( keys.filter(k => k !== CACHE_NAME).map(k => caches.delete(k)) )) ) }) // Fetch : Cache-First avec fallback réseau self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request).then(cached => { return cached || fetch(event.request).then(response => { const clone = response.clone() caches.open(CACHE_NAME).then(c => c.put(event.request, clone)) return response }) }).catch(() => caches.match('/offline.html')) ) })
Stratégies de cache
| Stratégie | Comportement | Cas d'usage |
|---|---|---|
| Cache First | Cache â RĂ©seau si absent | Assets statiques (CSS, JS, images) |
| Network First | RĂ©seau â Cache si offline | DonnĂ©es dynamiques (API, articles rĂ©cents) |
| Stale While Revalidate | Cache immédiat + revalidation async | Contenu mis à jour fréquemment |
| Cache Only | Cache uniquement, jamais réseau | Assets d'installation critique |
| Network Only | Réseau uniquement, jamais cache | Analytics, logs, POST critique |
vite-plugin-pwa), Next.js, Create React App.APIs Web modernes
Grùce au projet Fugu et aux standards W3C, les PWA accÚdent à des fonctionnalités de plus en plus proches des apps natives :
Notifications systĂšme, mĂȘme app fermĂ©e. Requiert permission explicite.
Lire et écrire des fichiers locaux avec dialogue de sélection. Pas de Firefox/Safari.
Synchroniser des données en arriÚre-plan quand la connexion revient.
Partager du contenu via la feuille de partage native du systĂšme.
GPS/localisation avec permission. Précision variable selon device.
AccÚs caméra et micro via getUserMedia(). Permission obligatoire.
Connexion à des périphériques Bluetooth LE. Limité et expérimental.
Base de données locale NoSQL. Stockage structuré cÎté client, multi-Go possible.
Lire/écrire des tags NFC depuis Android Chrome.
Afficher un badge numérique sur l'icÎne de l'app installée.
EmpĂȘcher l'Ă©cran de se verrouiller pendant l'utilisation.
Encodage/décodage vidéo natif et accÚs GPU pour calcul et rendu haute performance.
Installation A2HS & Desktop
Add to Home Screen (A2HS) est le mĂ©canisme par lequel une PWA peut ĂȘtre installĂ©e sur l'Ă©cran d'accueil d'un mobile ou dans les applications du bureau.
let installPrompt = null // Capturer l'événement avant qu'il s'affiche automatiquement window.addEventListener('beforeinstallprompt', (e) => { e.preventDefault() installPrompt = e document.getElementById('btn-install').style.display = 'block' }) // Déclencher manuellement depuis un bouton "Installer l'app" document.getElementById('btn-install').addEventListener('click', async () => { if (!installPrompt) return installPrompt.prompt() const { outcome } = await installPrompt.userChoice console.log(outcome === 'accepted' ? 'App installée !' : 'Refusé') installPrompt = null })
| Plateforme | Mécanisme | Déclencheur |
|---|---|---|
| Android Chrome | BanniÚre native + beforeinstallprompt | Automatique ou bouton personnalisé |
| iOS Safari | Manuel via "Partager â Ajouter Ă l'Ă©cran d'accueil" | Indice visuel dans l'app recommandĂ© |
| Chrome / Edge Desktop | IcĂŽne â dans la barre d'adresse | Bouton personnalisĂ© ou automatique |
| Samsung Internet | BanniĂšre native | Automatique |
| Firefox Desktop | Pas d'installation PWA | N/A |
Performance â Lighthouse
Google Lighthouse est l'outil de référence pour auditer une PWA. Une PWA "exemplaire" vise des scores élevés sur tous les axes :
Métriques Core Web Vitals
| Métrique | Signification | Cible |
|---|---|---|
| LCP â Largest Contentful Paint | Temps avant affichage du contenu principal | < 2.5s |
| INP â Interaction to Next Paint | RĂ©activitĂ© aux interactions utilisateur | < 200ms |
| CLS â Cumulative Layout Shift | StabilitĂ© visuelle (pas de sauts de mise en page) | < 0.1 |
| FCP â First Contentful Paint | Temps avant premier pixel visible | < 1.8s |
| TTFB â Time to First Byte | Vitesse de rĂ©ponse du serveur | < 800ms |
Compatibilité par navigateur
Limitations vs apps natives
| Limitation | Statut 2025 | Alternative |
|---|---|---|
| AccÚs filesystem complet | Chrome/Edge seulement (File System Access) | Téléchargement + input file |
| Bluetooth / USB / NFC | Chrome desktop/Android partiellement | Application native |
| Capteurs (accéléromÚtre, gyro) | Mobile Chrome/Safari, limité | React Native, app native |
| Push iOS (avant 16.4) | Résolu depuis iOS 16.4 (mars 2023) | App native si iOS <16.4 requis |
| Exécution en arriÚre-plan | Background Sync, pas d'exécution longue | App native pour tùches longues |
| Présence dans les stores | Possible via PWABuilder (Microsoft Store) | App native packagée |
| AccÚs contacts / calendrier | Non disponible (sauf Contact Picker limité) | App native |
| Performance GPU intensive | WebGPU disponible en 2024+ (Chromium) | App native pour jeux, ML |
PWA vs Electron vs Tauri
| CritĂšre | PWA | Electron | Tauri |
|---|---|---|---|
| Mobile (iOS/Android) | OUI (natif) | NON | BETA (v2) |
| Installation | Sans store | Installeur | Installeur |
| AccÚs systÚme | TrÚs limité | Complet | Complet |
| Taille distribuée | 0 Ko (URL) | ~150 Mo | ~5 Mo |
| Hors-ligne | Service Worker | Complet | Complet |
| Mises à jour | Instantanées | Via auto-updater | Via plugin updater |
| SEO / partage URL | OUI | NON | NON |
| AccÚs filesystem complet | NON (limité) | OUI | OUI |
| Courbe d'apprentissage | Faible | ModĂ©rĂ©e | ĂlevĂ©e (Rust) |
| Hébergement requis | OUI (HTTPS) | Non | Non |
Cas d'usage appropriés
| Cas d'usage | Pertinence | Raison |
|---|---|---|
| App web existante Ă "appifier" | EXCELLENT | Ajouter install + offline Ă un site web existant en quelques jours. |
| App universelle tous devices | EXCELLENT | Un seul code pour PC, Mac, Android, iOS sans build séparé. |
| Application à déploiement zero-friction | EXCELLENT | URL = distribution. Pas d'installeur, pas de store, pas de MAJ forcée. |
| Contenu offline (lectures, docs) | TRĂS BON | Service Worker + IndexedDB = expĂ©rience offline complĂšte. |
| Dashboard / outil mĂ©tier interne | TRĂS BON | AccĂšs navigateur uniquement, pas d'installation IT requise. |
| Outil nĂ©cessitant l'accĂšs complet aux fichiers | INSUFFISANT | Filesystem limitĂ© â prĂ©fĂ©rer Electron ou Tauri. |
| App systĂšme, pilotes, bas niveau | IMPOSSIBLE | Le bac Ă sable web interdit tout accĂšs systĂšme bas niveau. |
| Application de conversion vidéo lourde | LIMITà | WebCodecs + WebAssembly possible, mais accÚs fichiers limité hors Chrome. |