Comparez PWA, Flutter et natif (SwiftUI/Jetpack Compose) : performance, UX, hors‑ligne, APIs matérielles, distribution et adéquation à l'équipe — plus comment choisir.

Choisir entre une PWA, Flutter et le “natif” n'est pas seulement choisir un langage—c'est choisir un modèle de livraison produit.
Une PWA est un site web avec des capacités proches d'une application (installable, mise en cache pour le hors-ligne, notifications push dans certains environnements). Votre runtime principal est le navigateur, et la distribution se fait surtout via des liens.
Flutter est un toolkit UI multiplateforme qui s'expédie comme une application. Vous embarquez votre moteur de rendu et votre couche UI, visant un comportement cohérent sur iOS et Android tout en appelant les APIs de la plateforme quand nécessaire.
« Natif » aujourd'hui signifie généralement les SDKs de plateforme (iOS SDK d'Apple, Android SDK) plus des frameworks UI déclaratifs modernes : SwiftUI sur iOS et Jetpack Compose sur Android. On n'écrit plus l'UI "native à l'ancienne"—on écrit de l'UI déclarative native qui s'intègre profondément aux conventions de la plateforme, à l'accessibilité et aux composants système.
Cet article compare PWA vs Flutter vs natif (SwiftUI/Compose) comme choix de bout en bout : caractéristiques de performance, fidélité UX, capacités et charge opérationnelle—pas seulement « quel est le plus agréable à coder ».
Nous évaluerons chaque option selon un ensemble de questions cohérent :
Il n'existe pas de « meilleur universel ». La bonne réponse dépend de vos utilisateurs, de votre jeu de fonctionnalités, des compétences de votre équipe et de votre manière d'expédier et d'itérer.
Le choix entre PWA, Flutter et natif (SwiftUI/Jetpack Compose) est en grande partie un choix de runtime et de pipeline de rendu : où votre code s'exécute, qui dessine les pixels et comment vous accédez aux capacités de l'appareil.
Une PWA s'exécute dans le moteur du navigateur (WebKit sur iOS, moteurs basés sur Chromium sur la plupart des navigateurs Android). Votre code est du HTML/CSS/JavaScript exécuté par le moteur JS, et l'UI est produite par le système de mise en page et rendu du navigateur.
Éléments architecturaux clés :
En pratique, vous construisez sur un runtime web standardisé mais avec des variations et des contraintes entre navigateurs—surtout sur iOS.
Flutter embarque son propre framework UI et pipeline de rendu. Votre code Dart s'exécute dans le moteur Flutter (JIT en debug, compilé AOT en release). Plutôt que de s'appuyer sur des widgets natifs, Flutter dessine tout via Skia, produisant un rendu cohérent sur les plateformes.
Quand Flutter a besoin de fonctionnalités spécifiques (caméra, paiements, capteurs), il utilise des platform channels (ou plugins) pour appeler du code natif. Cette limite est explicite : itération UI rapide en Dart, plus des ponts natifs ciblés pour l'intégration plateforme.
Les apps natives s'exécutent directement sur le runtime de la plateforme (iOS : Swift/Obj‑C sur les frameworks Apple ; Android : Kotlin/Java sur ART). Avec SwiftUI et Jetpack Compose, vous écrivez une UI déclarative, mais le rendu est assuré par les toolkits système.
Cela signifie que les apps natives héritent du comportement plateforme « par défaut » : accessibilité, rendu du texte, entrée, navigation et composants système—sans couche de pont supplémentaire.
La performance, ce n'est pas que des benchmarks—c'est ce que ressent l'utilisateur : rapidité d'ouverture, fluidité du défilement et impression que les animations répondent immédiatement. Le même produit peut paraître premium ou lent selon la stack.
Natif (SwiftUI/Jetpack Compose) gagne généralement sur le cold start et la latence entrée→rendu car il s'exécute sur le runtime plateforme, profite de l'ordonnancement système et évite des couches d'abstraction supplémentaires. Les interactions à haute fréquence restent prévisibles.
Flutter peut être très fluide une fois lancé, car il dessine via son moteur. Cette cohérence permet d'obtenir des animations à 60/120fps quand l'UI est bien optimisée. Le démarrage peut être un peu plus lourd que le natif, et les animations très lourdes peuvent nécessiter du tuning (caching, éviter l'overdraw).
PWA s'améliore continuellement, mais reste limitée par le navigateur : exécution JS, recalculs DOM/layout et coût du rendu de pages complexes. Un défilement fluide est possible, mais de grandes structures imbriquées, des reflows fréquents et des scripts tiers lourds ajoutent rapidement du jank.
Les capacités d'arrière-plan influent indirectement sur la réactivité : pouvez‑vous pré‑charger, synchroniser silencieusement ou garder l'état à jour ?
Les écarts se voient surtout sur des feeds infinis, cartes avec overlays, chat / mises à jour en temps réel, grilles d'images lourdes et UIs riches en gestes. Pour des formulaires simples, du contenu ou des flux CRUD, une PWA ou une app Flutter bien conçue peut être assez rapide—le goulot est souvent le réseau et la gestion des données plutôt que le rendu.
La fidélité UI concerne moins la beauté visuelle que le comportement attendu : navigation, gestes, rendu du texte, haptiques et accessibilité. C'est là que PWA, Flutter et natif diffèrent le plus.
Natif gagne souvent sur le ressenti « ça sonne juste ». Glisser pour retourner, barres de navigation système, sélection de texte, physique du scrolling et comportements d'entrée suivent les mises à jour OS presque automatiquement.
Flutter peut reproduire beaucoup de conventions, mais il faut choisir : expérience cross‑platform unique ou adaptations par plateforme. En pratique, il faudra parfois du code distinct pour la navigation, l'évitement du clavier et la typographie.
PWA progresse, mais les contraintes du navigateur peuvent se traduire par des transitions non natives, une intégration de gestes limitée et des différences de rendu de police ou de comportement d'entrée.
Compose s'intègre naturellement à Material 3 ; SwiftUI s'aligne sur les patterns iOS. Flutter propose Material et Cupertino, plus un contrôle total pour un branding personnalisé. Le coût est la maintenance : une personnalisation lourde complexifie les montées de version et l'alignement plateforme.
Les PWAs peuvent implémenter n'importe quel système de design, mais vous recréez des composants que la plateforme fournit et que les utilisateurs reconnaissent.
Flutter excelle pour des UIs personnalisées et des animations fluides et cohérentes sur les appareils. Le natif est tout aussi puissant, mais les transitions avancées demandent parfois une connaissance plus profonde de la plateforme.
Les PWAs peuvent réaliser des mouvements impressionnants, mais les interactions complexes atteignent vite les limites de performance des appareils bas de gamme.
Les stacks natifs offrent les primitives d'accessibilité les plus fiables : rôles sémantiques, gestion du focus, Dynamic Type/augmentation de police et lecteurs d'écran système.
Flutter supporte bien l'accessibilité, mais il faut être rigoureux sur les sémantiques, l'ordre du focus et l'échelle du texte.
Les PWAs s'appuient sur le support web de l'accessibilité, qui peut être excellent—mais certains comportements de lecteurs d'écran mobiles et réglages système ne se traduisent pas parfaitement via le navigateur.
Le hors‑ligne est souvent le premier endroit où le « cross‑platform » cesse d'être identique. PWAs, Flutter et natif peuvent tous donner une impression offline‑first—mais différemment.
PWA : le Service Worker et une stratégie de cache (app shell + runtime caching) sont la base. Idéal pour les flux majoritairement en lecture (contenu, formulaires, checklists). Les écritures nécessitent une file d'attente locale, une logique de retry et une résolution de conflits (timestamps, vecteurs de version ou règles côté serveur). Le plus : règles de cache explicites ; le moins : quotas de stockage et exécution en arrière‑plan variables.
Flutter : vous contrôlez toute la pile cliente. Pattern typique : base locale + couche de sync (ex. repository avec table d'« outbox »). La résolution de conflits est équivalente au natif, et vous évitez bien des surprises liées à l'éviction de cache du navigateur.
Natif : meilleur choix quand les besoins offline sont stricts (gros jeux de données, durabilité garantie, règles complexes de conflit, sync en arrière‑plan). Vous avez aussi un contrôle plus fin sur les conditions réseau et l'ordonnancement OS.
PWA : IndexedDB est l'outil principal (données structurées, capacité correcte mais non garantie). Le stockage peut être effacé sous pression et le quota varie selon navigateur/appareil.
Flutter : SQLite, Realm via plugins, et stockage de fichiers sont courants ; la persistance est plus prévisible que dans un sandbox navigateur.
Natif : bases de données first‑class (Core Data/SQLite sur iOS, Room/SQLite sur Android) avec persistance et outils les plus fiables.
Push PWA : supporté sur Android/Chromium ; sur iOS le support existe mais est plus contraint et l'expérience utilisateur moins consistante.
Flutter/natif push : APNs et FCM offrent une livraison plus interchangeable, des contrôles riches, et une intégration plus profonde (canaux, alertes critiques où permises, deep links).
Sync périodique / tâches planifiées : les PWAs ont des options limitées et dépendantes du navigateur. Flutter peut utiliser les schedulers plateforme via des plugins, mais il faut respecter les limites iOS. Le natif offre le plus large éventail (BackgroundTasks iOS, WorkManager Android) et les meilleures chances d'exécution réelle.
Choisissez une PWA si les liens, le SEO et les déploiements instantanés sont prioritaires et que vous pouvez vivre avec les contraintes du navigateur (surtout sur iOS).
Choisissez Flutter si vous voulez une base de code unique iOS/Android avec un contrôle fort sur l'UI et que vous acceptez de gérer quelques ponts vers la plateforme.
Choisissez natif (SwiftUI/Compose) si vous avez besoin du meilleur niveau de finition plateforme, de performances prévisibles et des capacités profondes du système (background, APIs matérielles).
C'est principalement une décision de runtime + rendu :
En général, le natif l'emporte pour le démarrage à froid et la latence entrée→rendu puisqu'il utilise la pile système.
Flutter peut être extrêmement fluide une fois lancé, mais le cold start peut être un peu plus lourd et certaines animations graphiques demandent un ajustement.
PWA dépend fortement du coût JavaScript + DOM/layout ; les mises en page complexes et scripts tiers provoquent le plus souvent du jank.
Le natif est en règle générale le meilleur pour le ressenti “natif” : gestes de retour, sélection de texte, physique du scroll, gestion du clavier et navigation système.
Flutter peut atteindre ce résultat, mais nécessite souvent des ajustements par plateforme.
PWA peut être très belle visuellement, mais certaines transitions et comportements d'entrée restent limités ou variables selon le navigateur.
Les trois peuvent être offline-first, mais la fiabilité varie :
Pratique :
Pour le travail périodique en arrière-plan, (et Flutter via les APIs de plateforme) offre de meilleures options d'ordonnancement que les PWAs.
Si vous avez besoin de Bluetooth, NFC, Wallet/Health, SDKs fournisseurs ou modes d'arrière-plan avancés, le natif est le plus sûr.
Flutter peut gérer beaucoup d'APIs via des plugins, mais prévoyez du temps pour écrire des platform channels pour les cas limites.
PWA a un support plus restreint et incohérent sur mobile—particulièrement pour les fonctionnalités matérielles pointues.
PWA se met à jour quand vous déployez—pas d'examen en store pour la plupart des changements—donc les hotfixes sont très rapides.
Flutter/natif passent par l'App Store/Play Store, ce qui ajoute signature, cycles de revue (surtout iOS) et gestion des releases. Vous pouvez mitiger avec déploiements progressifs et feature flags, mais les binaires restent soumis aux stores.
Si vous dépendez de découverte via store ou d'achats intégrés pour des biens numériques, les apps store (natif/Flutter) sont la voie la plus directe—avec les contraintes de partage de revenus et de politiques.
Les PWAs peuvent utiliser des paiements web (ex. Stripe) quand c'est autorisé, ce qui améliore la flexibilité et la marge, mais peut être limité par les règles de plateforme et la confiance des utilisateurs.
Les coûts cachés proviennent souvent de la matrice de tests :
Étape pratique : listez vos fonctionnalités indispensables (push, sync background, BLE, paiements) et validez-les sur vos appareils cibles avant de vous engager.