Progressive Web Apps — Dossier 2026
← Retour

Progressive Web Apps — Dossier 2026

Cédrix · 15/05/2026

1. Qu'est-ce qu'une PWA ?

Une Progressive Web App est une application web qui, grâce à des APIs modernes des navigateurs, se comporte comme une application native : installable sur l'écran d'accueil, capable de fonctionner hors ligne, de recevoir des notifications push, de s'intégrer au système d'exploitation, tout en restant un site web indexable par les moteurs de recherche.

Le mot clé est progressive : l'expérience s'enrichit selon les capacités du navigateur et de l'appareil. Sur un Chrome récent sous Android, la PWA offre une expérience proche du natif ; sur un vieux navigateur, elle reste un site web fonctionnel.

Une PWA repose sur trois piliers techniques :

  • HTTPS obligatoire — sécurité et confiance, prérequis pour toutes les APIs sensibles.
  • Service Worker — un script JavaScript qui tourne en arrière-plan, intercepte les requêtes réseau, gère le cache et les notifications.
  • Manifest (manifest.webmanifest) — un fichier JSON qui décrit l'application (nom, icônes, couleurs, mode d'affichage) pour permettre son installation.

Trois critères définissent une PWA selon Google : elle doit être fiable (charge instantanément, même hors ligne), rapide (réagit vite aux interactions) et engageante (sensation d'application native, réengagement par notifications).

2. Histoire et promoteurs

L'idée d'une convergence web/natif n'est pas neuve. Steve Jobs, en 2007, présentait initialement l'iPhone sans App Store : les développeurs étaient censés faire des « web apps ». L'App Store est arrivé un an plus tard et a marginalisé cette vision pendant près d'une décennie.

Le terme « Progressive Web App » est proposé en 2015 par la designer Frances Berriman et l'ingénieur Google Alex Russell, pour désigner les sites tirant parti des nouvelles APIs (service workers notamment, standardisés à partir de 2014-2015).

Les promoteurs historiques :

  • Google — moteur principal. Pousse la spécification, intègre les PWA à Chrome, Android, ChromeOS, et au Play Store (depuis 2019, on peut publier une PWA empaquetée via TWA — Trusted Web Activity).
  • Microsoft — second souffle majeur. Edge intègre les PWA nativement, et Windows permet leur publication au Microsoft Store via packaging MSIX. En mai 2025, Edge a ajouté les App Actions on Windows pour les PWA, améliorant la découvrabilité système.
  • Mozilla — soutien historique des standards, support solide dans Firefox (bien que l'installation desktop ait été retirée puis partiellement réintégrée selon les versions).
  • Apple — adoption lente et réticente, voir section 6.

Les premiers grands déploiements (vers 2016-2017) ont servi de cas d'école : Twitter Lite, AliExpress, Pinterest, Flipkart, Starbucks, Uber, Tinder, Trivago. Tous ont publié des chiffres montrant des gains d'engagement et de conversion significatifs, ce qui a légitimé le modèle auprès des grandes entreprises.

3. Comment ça marche techniquement

3.1 Le manifeste

Fichier JSON déclaratif qui dit au navigateur : « ce site est installable, voici comment il doit se présenter ».

{
  "name": "Mon Application",
  "short_name": "MonApp",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#0066cc",
  "icons": [
    { "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png" }
  ]
}

Référencé dans le HTML :

<link rel="manifest" href="/manifest.webmanifest">
<meta name="theme-color" content="#0066cc">

Le mode display: standalone retire la barre d'adresse au lancement depuis l'écran d'accueil ; fullscreen masque même la barre système.

3.2 Le Service Worker

Script JavaScript qui s'exécute dans un thread séparé, sans accès direct au DOM, et qui agit comme un proxy programmable entre l'application et le réseau.

// sw.js
const CACHE_NAME = 'app-v1';
const ASSETS = ['/', '/index.html', '/styles.css', '/app.js', '/icons/icon-192.png'];

// Installation : on précharge les ressources critiques
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => cache.addAll(ASSETS))
  );
});

// Activation : on nettoie les 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 : stratégie cache-first, puis réseau en fallback
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then((cached) => cached || fetch(event.request))
  );
});

Enregistrement depuis la page principale :

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js');
}

3.3 Stratégies de cache

Quatre patterns canoniques selon le type de ressource :

  • Cache-first — sert le cache, va sur le réseau si absent. Idéal pour les assets statiques (CSS, JS, polices).
  • Network-first — tente le réseau, retombe sur le cache en cas d'échec. Idéal pour les contenus dynamiques (articles, posts).
  • Stale-while-revalidate — sert le cache immédiatement, met à jour en arrière-plan. Bon compromis pour les contenus semi-dynamiques (listes, avatars).
  • Network-only / Cache-only — cas particuliers (analytics, données critiques).

3.4 Les APIs modernes mobilisables

En 2026, l'écosystème PWA s'appuie sur un éventail large :

  • Push API + Notifications API — notifications push, y compris sur iOS 16.4+ (sous conditions).
  • Background Sync — différer une requête jusqu'au retour de la connectivité (Chrome/Edge ; pas sur iOS).
  • Periodic Background Sync — déclencher du code à intervalle régulier (Chrome/Edge uniquement).
  • Web Share API — utiliser le menu de partage natif du système.
  • File System Access API — lire/écrire dans des fichiers locaux (Chrome/Edge).
  • WebGPU, WebAssembly SIMD, WebNN — calcul intensif et inférence IA côté client.
  • Badging API — afficher un badge numérique sur l'icône d'app.
  • Web Bluetooth, Web USB, Web Serial — accès matériel (Chrome/Edge, hors iOS).
  • Payment Request API — paiements unifiés, dont Apple Pay sur Safari.

4. Exemples emblématiques

Les références suivantes ont structuré la perception du modèle PWA. Les chiffres sont ceux publiés par les entreprises à l'époque de leur migration.

Twitter Lite (2017) — Twitter a déployé une PWA pesant moins de 1 Mo (contre 23 Mo pour l'app native Android). Résultat : +65 % de pages par session, +75 % de tweets envoyés, −20 % de taux de rebond. Nicolas Gallagher, alors lead du projet, résumait : « Twitter Lite is now the fastest, least expensive, and most reliable way to use Twitter. »

AliExpress — Migration de leur site mobile vers une PWA. Doublement du temps passé par session, +104 % de taux de conversion pour les nouveaux utilisateurs sur tous les navigateurs.

Pinterest — Refonte en PWA en 2017. Le poids initial du bundle JavaScript est passé de 650 Ko à 150 Ko. Temps passé +40 %, revenus publicitaires +44 %, engagement utilisateur +60 %.

Starbucks — Une PWA pour la commande en ligne, environ 600 Ko (contre 148 Mo pour l'app iOS native). Double des commandes quotidiennes via le web, avec des chiffres particulièrement marqués sur les marchés à faible bande passante.

Spotify, Uber, Tinder, Trivago, BMW, Forbes, The Washington Post — Tous ont déployé des versions PWA, soit en remplacement de leur site mobile, soit en complément de l'app native.

Note d'objectivité : ces cas remontent majoritairement à 2017-2019. Beaucoup ont été suivis d'allers-retours stratégiques (certaines entreprises ont depuis re-priorisé le natif pour des raisons de fonctionnalités ou de distribution). Twitter, par exemple, a depuis fait évoluer son web app et son app native en parallèle. Ces chiffres restent illustratifs d'un potentiel, pas d'une vérité universelle.

5. Où en est-on en 2026 ?

5.1 Maturité du modèle

Trois leviers ont fait basculer les PWA d'une expérimentation à une option pragmatique :

  1. Maturité des APIs clés — service worker stable, manifest standardisé, Web Push enfin disponible sur Safari (iOS 16.4+).
  2. Intégration croissante par les OS et stores — packaging MSIX vers le Microsoft Store, TWA vers le Play Store, App Actions sur Windows, mode app par défaut sur iOS 26.
  3. Preuves de ROI répétées sur une décennie de déploiements.

5.2 Chiffres du marché

Les estimations convergent vers une croissance soutenue. Selon Research Nester, le marché mondial des PWA dépassait 2,47 Md$ en 2025, est estimé à 3,14 Md$ en 2026, avec une projection à 34,58 Md$ d'ici 2035 (TCAC supérieur à 30 %).

L'adoption reste cependant concentrée : selon les datasets publics (HTTP Archive / Web Almanac), une fraction modeste des sites déclarent un service worker, mais ces sites représentent une part disproportionnée du trafic mondial — autrement dit, ce sont les gros sites qui adoptent.

5.3 Nouveautés récentes

  • Declarative Web Push (Safari 18.4, 2025) — alternative simplifiée au Web Push impératif, ne nécessitant pas de service worker pour des notifications basiques.
  • App Actions on Windows pour les PWA (Edge, mai 2025) — les PWA peuvent déclarer des actions invocables depuis la barre de recherche Windows.
  • iOS 26 — tout site ajouté à l'écran d'accueil s'ouvre par défaut en mode application, même sans manifest. Avancée notable côté Apple.
  • WebGPU, WebNN, WebAssembly SIMD — débloquent l'inférence IA côté client, ouvrant la voie à des PWA capables de traitements lourds locaux (vision, NLP, recommandation).

5.4 Verrous résiduels

  • Découvrabilité — beaucoup d'utilisateurs ne savent pas qu'« ajouter à l'écran d'accueil » installe une vraie app. Pas de prompt automatique sur iOS.
  • Fragmentation des APIs — Chrome/Edge avancent vite, Safari traîne, Firefox se positionne au cas par cas. Le détection de feature reste obligatoire.
  • Stockage — quotas plus stricts sur iOS qu'ailleurs, avec un risque d'éviction du cache après 7 jours sans utilisation sur certaines configurations.
  • Monétisation — pas de système intégré de paiement in-app comme l'App Store. Il faut passer par Stripe, Apple Pay via Payment Request, etc.

6. Le cas iOS : limites et particularités

Apple a toujours été le frein principal à l'adoption universelle des PWA. Les raisons sont à la fois techniques et stratégiques (revenus de l'App Store, contrôle de la plateforme, monopole de WebKit).

Ce qui marche en 2026 sur iOS :

  • Installation manuelle sur l'écran d'accueil (mais pas de prompt automatique).
  • Mode standalone (fenêtre sans barre d'adresse).
  • Service workers (avec des quotas et limitations).
  • Push notifications, uniquement si la PWA a été installée à l'écran d'accueil (depuis iOS 16.4).
  • Apple Pay via Payment Request API.
  • Géolocalisation, caméra, microphone.

Ce qui ne marche pas ou mal :

  • Pas de Background Sync ni de Periodic Background Sync.
  • Pas de Web Bluetooth, Web USB, Web NFC.
  • Stockage limité, susceptible d'être purgé sans usage.
  • Pas de silent push ni de réveil en arrière-plan.
  • L'audience effectivement joignable par push est environ 10 à 15 fois plus petite que sur app native, une fois pris en compte le parcours d'installation multi-étapes.

Le détour DMA en Europe : en 2024, Apple a brièvement annoncé supprimer le mode standalone pour les PWA dans l'UE (iOS 17.4) au prétexte du Digital Markets Act, ce qui aurait réduit les PWA à de simples raccourcis Safari. Décision rapidement annulée après tollé : le support PWA complet a été rétabli dans l'UE. Épisode révélateur de la position ambiguë d'Apple.

Verdict pratique 2026 : Apple a fait des progrès (push en 16.4, Declarative Web Push en 18.4, app mode par défaut en iOS 26), mais à un rythme lent et avec des marges de manœuvre étroites. Pour un projet ciblant fortement iOS et reposant sur du push fiable, du background sync ou de l'intégration profonde au système, le natif (ou hybride) reste l'option plus sûre.

7. PWA vs natif vs hybride

Critère PWA Natif (iOS/Android) Hybride (RN, Flutter)
Codebase Unique (web) 2 séparés 1 partagé, ponts natifs
Distribution URL + stores optionnels App Store, Play Store obligatoires Stores obligatoires
Mises à jour Instantanées Validation store (jours) Validation store
Découvrabilité SEO Oui (indexé Google) Non Non
Coût de dev (typique) 2-3× 1,3-1,8×
Performance UI Bonne à très bonne Maximale Très bonne
Accès matériel Partiel, variable selon OS Total Quasi-total
Notifications push iOS Oui, sous conditions Oui, sans conditions Oui
Frais store (achats numériques) 0 % 15-30 % 15-30 %
Hors ligne Oui via service worker Oui Oui

Quand choisir une PWA

  • Audience web-first (desktop + mobile navigateur).
  • SEO comme canal d'acquisition stratégique.
  • Time-to-market et coût de maintenance prioritaires.
  • Contenu plutôt que fonctionnalités matérielles avancées.
  • Marchés émergents (stockage, bande passante limités).
  • Outils internes B2B, portails, contenus éditoriaux, e-commerce léger.

Quand préférer le natif

  • Accès matériel profond (BLE, NFC, capteurs avancés, ARKit/ARCore).
  • Performances graphiques 120 fps, jeux, AR/VR.
  • Monétisation reposant sur l'achat in-app via stores.
  • Marque dépendant fortement de la présence App Store/Play Store.

Quand choisir hybride (React Native, Flutter)

  • Présence store nécessaire mais sans le budget de deux codebases natives.
  • Équipe JavaScript ou Dart.
  • Besoins matériels modérés mais réels.

8. Pour commencer : un MVP en 4 fichiers

Voici la PWA minimale viable. Quatre fichiers, aucun framework, déployable sur n'importe quel hébergement HTTPS.

index.html

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Ma PWA</title>
  <link rel="manifest" href="/manifest.webmanifest">
  <meta name="theme-color" content="#0066cc">
  <link rel="apple-touch-icon" href="/icons/icon-192.png">
</head>
<body>
  <h1>Bonjour</h1>
  <p>Ceci est une PWA.</p>
  <script>
    if ('serviceWorker' in navigator) {
      window.addEventListener('load', () => {
        navigator.serviceWorker.register('/sw.js')
          .then((reg) => console.log('SW enregistré', reg.scope))
          .catch((err) => console.error('Échec SW', err));
      });
    }
  </script>
</body>
</html>

manifest.webmanifest

{
  "name": "Ma Progressive Web App",
  "short_name": "MaPWA",
  "description": "Démonstration minimale d'une PWA.",
  "start_url": "/",
  "scope": "/",
  "display": "standalone",
  "orientation": "portrait",
  "background_color": "#ffffff",
  "theme_color": "#0066cc",
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any maskable"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any maskable"
    }
  ]
}

sw.js

const CACHE_NAME = 'mapwa-v1';
const PRECACHE = [
  '/',
  '/index.html',
  '/manifest.webmanifest',
  '/icons/icon-192.png',
  '/icons/icon-512.png'
];

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => cache.addAll(PRECACHE))
  );
  self.skipWaiting();
});

self.addEventListener('activate', (event) => {
  event.waitUntil(
    caches.keys().then((keys) =>
      Promise.all(
        keys.filter((k) => k !== CACHE_NAME).map((k) => caches.delete(k))
      )
    )
  );
  self.clients.claim();
});

self.addEventListener('fetch', (event) => {
  // Stale-while-revalidate pour les navigations
  if (event.request.mode === 'navigate') {
    event.respondWith(
      caches.match(event.request).then((cached) => {
        const fresh = fetch(event.request).then((response) => {
          caches.open(CACHE_NAME).then((c) => c.put(event.request, response.clone()));
          return response;
        }).catch(() => cached);
        return cached || fresh;
      })
    );
    return;
  }
  // Cache-first pour le reste
  event.respondWith(
    caches.match(event.request).then((cached) => cached || fetch(event.request))
  );
});

Icônes

Deux fichiers PNG : icons/icon-192.png (192×192) et icons/icon-512.png (512×512). L'attribut purpose: "any maskable" permet à Android de découper l'icône selon la forme système (cercle, squircle, etc.).

Servir le tout en HTTPS (obligatoire en production ; localhost fonctionne en dev). Configuration nginx/Apache : s'assurer que manifest.webmanifest est servi avec le content-type application/manifest+json et que sw.js n'est jamais mis en cache HTTP côté navigateur (sinon les mises à jour ne se propagent pas).

location = /sw.js {
  add_header Cache-Control "no-store, no-cache, must-revalidate";
  expires off;
}

location = /manifest.webmanifest {
  add_header Content-Type "application/manifest+json";
}

Tester avec Lighthouse (intégré à Chrome DevTools, onglet Lighthouse puis catégorie Progressive Web App) — fournit un score, identifie les manques, propose des corrections.

9. Outils et frameworks

Workbox (Google) — la bibliothèque de référence pour les service workers. Génère du SW à partir de configurations déclaratives, gère les stratégies de cache, le préchargement, la mise à jour. Souvent utilisée via un plugin de bundler.

Vite PWA Plugin (vite-plugin-pwa) — l'option la plus simple pour un projet moderne basé sur Vite. Wrap Workbox, génère manifest et SW automatiquement.

Next.js — supporte les PWA via next-pwa (basé sur Workbox).

Nuxt@vite-pwa/nuxt officiel.

Angular, Vue, Svelte — tous disposent d'intégrations PWA officielles ou bien maintenues.

PWA Builder (Microsoft) — outil web qui audit un site et génère le packaging pour les stores (MSIX pour Microsoft, TWA pour Play Store).

Lighthouse — audit intégré à Chrome DevTools. Standard de fait pour vérifier la conformité PWA.

Côté PHP (pertinent au regard du contexte de cette doc) — Symfony et Laravel n'ont pas d'extension PWA officielle, mais l'intégration est triviale puisqu'une PWA n'exige côté serveur que de servir correctement quelques fichiers statiques en HTTPS. Bundles comme friendsofsymfony/elastica-bundle ne couvrent pas le sujet ; c'est plutôt à l'asset pipeline (Webpack Encore, Vite) de gérer la génération du service worker.

10. Pièges fréquents et bonnes pratiques

Le service worker piégé en cachesw.js lui-même ne doit jamais être mis en cache HTTP, sinon les utilisateurs restent bloqués sur une ancienne version. Cache-Control: no-store strict côté serveur.

Versionner le cache — toujours inclure une version dans le nom du cache (mapwa-v1, mapwa-v2...) et purger les anciens à l'activation. Sans cela, des assets périmés peuvent persister indéfiniment.

Ne pas tout cacher — précharger uniquement le strict nécessaire au shell de l'application. Le reste doit être mis en cache à la demande, avec une stratégie adaptée.

Tester hors ligne — Chrome DevTools propose un mode Offline dans l'onglet Network. C'est le seul moyen de vérifier que les stratégies de cache fonctionnent.

Gérer la mise à jour — quand un nouveau service worker est détecté, il s'installe mais n'est actif qu'après fermeture de tous les onglets de la PWA. Soit forcer via skipWaiting() + clients.claim() (rapide mais peut casser une session en cours), soit afficher à l'utilisateur une bannière « nouvelle version disponible ».

Détection de feature, jamais détection de navigateurif ('serviceWorker' in navigator), if ('PushManager' in window). Ne jamais sniffer userAgent.

Tester sur iOS réel — l'émulateur Safari ne reproduit pas toutes les limitations. Un iPhone physique est indispensable pour valider l'expérience.

HTTPS impératif — même en pré-prod. Les certificats Let's Encrypt sont gratuits ; un reverse proxy bien configuré (Caddy, nginx, Traefik) suffit. NB : ce point recoupe directement la configuration habituelle d'un homelab avec reverse proxy.

Manifest et icônes adaptatives — utiliser purpose: "maskable" avec des icônes ayant une zone de sécurité de ~10 % autour du contenu, sinon Android va découper dans le visuel.

Pas de prompt d'installation intrusif — Chrome déclenche automatiquement un mini-info-bar quand les critères PWA sont remplis. Si on veut un prompt personnalisé, intercepter l'événement beforeinstallprompt et le déclencher au moment opportun (jamais au premier chargement).

let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
  e.preventDefault();
  deferredPrompt = e;
  // Afficher un bouton « Installer » dans l'UI
  document.querySelector('#install-btn').hidden = false;
});

document.querySelector('#install-btn').addEventListener('click', async () => {
  if (!deferredPrompt) return;
  deferredPrompt.prompt();
  const { outcome } = await deferredPrompt.userChoice;
  console.log('Choix utilisateur :', outcome);
  deferredPrompt = null;
});

11. Ressources

Documentation officielle

Outils

Veille

  • Web Almanac (HTTP Archive) — rapport annuel sur l'état du web, chapitre PWA.
  • Can I Use : https://caniuse.com/ — compatibilité navigateur pour chaque API.

Études de cas


Document de référence — état au 13 mai 2026. À revoir tous les 6 à 12 mois, l'écosystème évoluant rapidement (notamment côté Apple).

Commentaires

Aucun commentaire pour l'instant. Soyez le premier !

Laisser un commentaire
Un code de vérification sera envoyé à votre adresse email.