Flutter web + Wasm : quand l'app métier doit vivre dans le navigateur
Flutter web Wasm 2026 : dart2wasm et skwasm livrent 2× en frame time, mais iOS Safari ne suit pas. Guide migration PME, benchmarks réels, et les trois cas où Wasm n'est pas votre problème.
Flutter web + Wasm : quand l'app métier doit vivre dans le navigateur
Wasm ne transforme pas un site vitrine. Il accélère un dashboard qui saccade.
Le 17 août 2026, Flutter a lancé la WebAssembly Week avec un headline séduisant : jusqu'à 2× à 5× plus rapide en compilant en Wasm. Le blog Flutter cite Chrome 151, M4 Pro, 48 Go, frame time 17,4 ms contre 34,5 ms en JS.
C'est un labo. Pas votre back-office.
Cet article ne répète pas la doc Flutter. Il répond à une question précise : votre app Flutter web doit-elle compiler en Wasm cette semaine ? On passe par les benchmarks réels, les pièges iOS, les headers obligatoires, et les trois cas où Wasm n'est pas votre problème.
Le Wasm en 30 secondes
Flutter web peut compiler Dart de deux façons :
| dart2js (défaut) | dart2wasm + skwasm | |
|---|---|---|
| Compilation | Dart → JavaScript | Dart → WebAssembly + WasmGC |
| Rendu | CanvasKit sur thread principal | CanvasKit sur Web Worker dédié |
| Frame time (labo) | 34,5 ms | 17,4 ms (×2) |
| Widget build | 29,3 ms | 11,4 ms (×2,5) |
| Jitter | ±1,5 ms | ±0,5 ms (×3) |
| Bundle total | baseline | +≤5 % (wasm + js fallback) |
| iOS Safari | Full | Fallback JS |
Deux technologies se cachent derrière le flag --wasm :
- dart2wasm : le compilateur Dart produit du WebAssembly natif, exécuté via WasmGC. Pas de JIT warmup, pas de parsing JS. Le code tourne directement en machine code.
- skwasm : le raster canvas (le thread qui peint les pixels) est déporté sur un Web Worker. Le thread principal ne fait que le build des widgets (state, layout, paint). Parallélisme natif.
Le gain est réel mais pas uniforme. Il dépend de combien votre app passe du temps sur du compute Dart (build, filtre, tri, chart redraw) versus du réseau (appels API, images).
dart2js produit du JS, dart2wasm produit du WebAssembly. skwasm ajoute le rendu multithread via Web Worker.
Benchmarks : labo vs production
Chiffres officiels Flutter (17 août 2026)
Le blog Flutter affiche des résultats sur un test « medium stress » (200 animated churn nodes) :
| Métrique | JS (dart2js) | Wasm (dart2wasm + skwasm) | Gain |
|---|---|---|---|
| Frame time total | 34,5 ms | 17,4 ms | ×2 |
| Widget build time | 29,3 ms | 11,4 ms | ×2,5 |
| Frame jitter (σ) | ±1,5 ms | ±0,5 ms | ×3 |
| Taille bundle comprimé | baseline | ≤+5 % | +5 % |
Mesuré sur Chrome 151, MacBook Pro M4 Pro (48 Go), macOS Sequoia 15.7.7, affichage 60 Hz.
Benchmarks tiers : trois apps de production
Flutter Studio a migré trois apps réelles de CanvasKit/JS à Skwasm/Wasm (même machine, même Chrome, 5 runs, cache vidé) :
App Fintech (charts, agrégation de données) :
| Métrique | JS | Wasm | Delta |
|---|---|---|---|
| Time to first paint | 3,2 s | 2,1 s | −34 % |
| Time to interactive | 4,8 s | 3,0 s | −38 % |
| Chart redraw (200 pts) | 180 ms | 95 ms | −47 % |
| List scroll (10K items) | 42 fps | 58 fps | +38 % |
App Logistique (carte, filtres, 5K enregistrements) :
| Métrique | JS | Wasm | Delta |
|---|---|---|---|
| Time to first paint | 2,6 s | 1,8 s | −31 % |
| Time to interactive | 3,5 s | 2,4 s | −31 % |
| Map render (500 markers) | 320 ms | 210 ms | −34 % |
| Filter 5K records | 85 ms | 45 ms | −47 % |
| Mémoire steady state | 112 Mo | 98 Mo | −13 % |
App Inventaire (tableaux, scan codes-barres) :
| Métrique | JS | Wasm | Delta |
|---|---|---|---|
| Time to first paint | 1,9 s | 1,4 s | −26 % |
| Data table sort (2K rows) | 65 ms | 38 ms | −42 % |
| Barcode scan + lookup | 140 ms | 90 ms | −36 % |
| Mémoire steady state | 85 Mo | 76 Mo | −11 % |
La constante : 25–40 % plus rapide au chargement, 30–47 % sur le compute, 10–13 % de mémoire en moins. Les apps les plus gagnantes sont celles avec le plus de calcul Dart (charts, filtres, tri). Les pages texte montrent moins de gain car le goulot est le réseau et les fonts.
FluxBoard (démo publique, Andrea Della Porta)
En scrollant un tableau de 5 000 lignes avec charts animés :
| JS | Wasm | |
|---|---|---|
| FPS moyen | ~34 fps | ~60 fps |
| Build time | ~26 ms | ~16,5 ms |
| Frames droppées | ~89 | 0 |
Le gain est ~×1,6 sur le build — suffisant pour franchir la ligne des 60 fps. La démo est publique sur GitHub (FluxBoard).
Piège iOS : le mur WebKit
Voici le chiffre qu'aucun article « Flutter Wasm ready » ne met en avant : iOS ne supporte pas WasmGC.
- Tous les navigateurs iOS utilisent WebKit (imposé par Apple).
- WebKit ne supporte pas WasmGC.
- Flutter sur iOS Safari utilise toujours le fallback JS (dart2js).
- Chrome iOS utilise aussi WebKit (pas Chromium). Pas de WasmGC non plus.
Conséquences :
- Si vos commerciaux utilisent des iPads en terrain, ils ne bénéficient pas du gain Wasm. L'app fonctionne (fallback JS), mais les 2× en frame time ne s'appliquent pas.
- Firefox 120+ déclare WasmGC stable, mais un bug empêche le rendu Flutter. Firefox tombe sur JS aussi.
- En pratique, Wasm tourne vraiment mieux que sur Chrome et Edge uniquement en août 2026.
Vérifiez votre parc utilisateur avant de pitcher Wasm comme « grosse amélioration pour tout le monde ».
##dart:html est mort pour Wasm
La condition n°1 pour compiler en --wasm : zéro import de dart:html ou package:js. La doc Flutter le dit explicitement. La raison est technique : dart:html dépend de l'interop JS legacy, incompatible avec WasmGC.
Migration vers package:web
| Ancien (legacy) | Nouveau (Wasm-ready) |
|---|---|
import 'dart:html' | import 'package:web/web.dart' |
import 'dart:js' | import 'dart:js_interop' |
@JS() de package:js | @JS() de dart:js_interop |
Diagnostic
# Dry-run (affiche les warnings sans --wasm)
flutter build web
# Build Wasm (échec si dart:html présent)
flutter build web --wasm
Le dry-run affiche :
Wasm dry run failed:
Found incompatibilities with WebAssembly.
package:my_app/main.dart 1:1 - dart:html unsupported (0)
Le build échoué affiche un arbre de dépendances structuré :
Context: The unavailable library 'dart:html' is imported through these packages:
main.dart => package:my_app => dart:html
Temps estimé
| Surface dart:html | Migration estimée |
|---|---|
| Zéro (déjà package:web) | Immédiat |
| 1–3 packages tierces | 1–3 jours |
| Interop maison | 3–7 jours |
| Wrapper complet | 1–2 semaines |
Le conditional import existe pour migrer progressivement :
import 'fallback.dart'
if (dart.library.js) 'legacy_web_interop.dart'
if (dart.library.js_interop) 'wasm_web_interop.dart';
Pas un hack. Mécanisme officiel Dart.
dart:html vers package:web. Le dry-run vous dit exactement quoi corriger.
COOP/COEP : headers obligatoires pour le multithread
Pour que skwasm tourne en multithread (raster sur Web Worker), le navigateur exige un environnement cross-origin isolated. Deux headers HTTP :
| Header | Valeur acceptée |
|---|---|
Cross-Origin-Embedder-Policy | credentialless ou require-corp |
Cross-Origin-Opener-Policy | same-origin |
Sans ces headers
- Flutter fonctionne en single-thread. Le build et le raster tournent sur le même thread.
- Le gain dart2wasm subsiste (compiler en wasm reste plus rapide que dart2js), mais le raster n'est plus parallèle.
- Vous perdez le facteur ×3 en jitter.
Configuration par hébergeur
| Hébergeur | Comment |
|---|---|
| Vercel | vercel.json → headers array |
| Nginx | add_header Cross-Origin-Embedder-Policy "credentialless"; |
| Firebase Hosting | firebase.json → headers |
| Cloudflare Pages | fichier _headers à la racine |
| Netlify | fichier _headers à la racine |
| Hostinger | .htaccess ou panneau de configuration |
Vérification
DevTools Chrome → onglet Application → vérifier Cross-Origin-Isolation.
Piège COEP + iframes tierces
Si votre app intègre des iframes tierces (Stripe, Cal.com embed, Google Maps), credentialless peut les bloquer. credentialless est plus permissif que require-corp. Utilisez credentialless sauf si votre iframe a besoin de credentials.
Sans COOP/COEP : single-thread. Avec : raster sur Web Worker. Le jitter drop de ×3.
Le bundle grossit, pas rétrécit
Point contre-intuitif : le build --wasm produit deux fichiers :
main.dart.wasm(pour les navigateurs WasmGC)main.dart.js(fallback pour les autres)
Le navigateur choisit au runtime. Le bundle total fait +≤5 % en comprimé (chiffre officiel Flutter). Des mesures tierces : +200 à 500 ko.
L'avantage n'est pas la taille mais la vitesse d'exécution. Si vous optimisez pour la bande passante 3G, le code splitting et l'optimisation des images restent vos priorités.
Flags de debug
# Production : source maps pour Sentry/Datadog
flutter build web --wasm --source-maps
# Staging : noms de fonctions dans la console
flutter build web --wasm --no-strip-wasm
--source-maps produit main.dart.wasm.map. --no-strip-wasm garde les noms de fonctions mais ajoute ~47 % à la taille Wasm. Ne jamais mettre --no-strip-wasm en prod.
Détection runtime
const isRunningWithWasm = bool.fromEnvironment('dart.tool.dart2wasm');
Utile pour logging, analytics, ou bifurcation conditionnelle.
Le SEO trade-off (indépendant de Wasm)
Flutter web est un SPA. Le HTML renvoyé est quasi vide. Google crawl le JavaScript mais tous les crawlers ne l'exécutent pas. Wasm ne change rien au SEO : le crawl dépend de l'exécution JS, pas du format de compilation.
- dart2js → crawlé comme du JS.
- dart2wasm → crawlé comme du JS (le navigateur exécute le wasm comme du JS).
Si vous avez besoin de pages indexables avec du contenu, SSR requis. Flutter n'a pas de SSR mature en 2026 (Frog est expérimental). Pour un site avec du contenu indexable, Next.js reste le choix le plus robuste.
Wasm n'est pas un argument pour migrer un site vitrine vers Flutter.
Trois cas, trois décisions
1. Back-office interne (dashboard, outil métier, suivi production)
→ Migrer. App compute-heavy, parc navigateur contrôlé (Chrome sur postes internes), pas de SEO. Le gain 25–40 % est mesurable par les utilisateurs.
Étapes : flutter upgrade → dry-run → package:web → --wasm staging → COOP/COEP → DevTools comparison → prod.
Risque : un commercial sur iPad Safari ne verra pas le gain. Acceptez-le ou standardisez Chrome.
2. App publique (accessibles sur internet)
→ Tester, pas promettre. Parc utilisateur hétérogène (Safari, Firefox, Chrome). Le fallback JS couvre tout le monde, mais le gain Wasm ne s'applique qu'à Chrome/Edge.
Avant de migrer : GA4 → navigateurs. Si > 50 % Chrome/Edge, Wasm est pertinent. Si > 40 % Safari, le gain est dilué.
Risque SEO : Wasm ne résout pas le problème de crawl. Le contenu reste du JS pour les moteurs de recherche.
3. Pas d'app Flutter web
→ Ignorer. Wasm ne transforme pas Next.js. Il n'accélère pas WordPress. Il ne crée pas un site vitrine. Le blog Flutter du 17 août parle aux équipes qui ont déjà du Flutter web en production.
Si votre besoin est un site qui prend des RDV, regardez site vitrine vs prise de RDV. Si c'est une app mobile, regardez Flutter vs React Native.
Dashboard interne Chrome → migrer. App publique → tester. Pas de Flutter web → ignorer.
Checklist de migration
flutter upgrade→ 3.47+flutter build web(sans--wasm) → lire les warnings dry-run- Si dart:html → migrer vers
package:web flutter build web --wasm→ si échec, lire l'arbre de dépendances- Configurer COOP same-origin + COEP credentialless
- DevTools → Application → Cross-Origin-Isolation → vérifier
- Mesurer : Performance tab → frame time, jank, build time
- Comparer avec build JS sur la même page
- Si gain > 20 % sur les pages compute-heavy → candidat prod
- Si gain < 10 % → app pas compute-heavy → rester en JS
- Tester Safari iOS (fallback JS) et Firefox (fallback JS)
- Si parc > 40 % Safari → Wasm est un bonus, pas une requirement
Ce que Wasm ne fait PAS
- Accélérer le réseau. Un appel API à 500 ms reste à 500 ms. Wasm n'est pas un CDN.
- Améliorer le SEO. Les crawlers ne voient pas le contenu Dart. SSR reste séparé.
- Réduire le bundle. Le bundle grossit de ~5 % (wasm + js fallback).
- Tourner sur iOS Safari. WasmGC pas supporté sur WebKit. Fallback JS uniquement.
- Résoudre un problème d'architecture Dart. Si votre app rebuild tout au setState, Wasm accélère mais ne refacto pas.
- Remplacer une refonte. Wasm est un optimiseur de rendu, pas un designer UX.
FAQ
Flutter web Wasm est-il prêt pour la production en 2026 ?
Oui, avec des réserves. WasmGC est stabilisé depuis Flutter 3.22 (mai 2024). 58 % des apps Flutter web existantes compilent en Wasm sans changement de code. Chrome 119+ supporte WasmGC. Firefox 120+ déclare WasmGC stable mais un bug bloque le rendu Flutter. Safari supporte WasmGC mais un bug similaire bloque Flutter. Tous les navigateurs iOS utilisent WebKit, pas de WasmGC. Le fallback JS est toujours inclus.
Faut-il des headers COOP/COEP pour Flutter web Wasm ?
Oui, pour le rendu multithread via skwasm. Sans COEP credentialless + COOP same-origin, Flutter tourne en single-thread. La perf reste meilleure que dart2js mais le raster parallèle sur Web Worker est désactivé. Configurez-les sur votre hébergeur et vérifiez dans les DevTools Chrome.
Le bundle Wasm est-il plus petit que le bundle JS ?
Non. Le build --wasm produit main.dart.wasm ET main.dart.js (fallback). Bundle total +~5 % comprimé (+200 à 500 ko). Le gain est dans l'exécution (25–40 %), pas dans la taille.
Par quoi commencer si mon équipe a une app Flutter web ?
flutter upgradevers 3.47+. 2)flutter build websans--wasmpour lire les warnings. 3) Corriger dart:html verspackage:web. 4)flutter build web --wasmen staging. 5) Configurer COOP/COEP. 6) Mesurer avec DevTools Chrome. 7) Comparer les temps de frame. 8) Si gain > 20 % shippez. Si < 10 % restez en JS.
Et si on est encore en Flutter 3.22 ?
Le WasmGC est stabilisé depuis 3.22. Mais les optimisations skwasm et les fixes de headers ont évolué depuis. Mettez à jour en staging d'abord. Le dry-run fonctionne sur 3.22.
Conclusion
Flutter web Wasm en 2026 n'est pas une révolution universelle. C'est un outil de performance ciblé. Les gains sont réels (25–40 % au chargement, ×2 en frame time, ×3 en jitter) mais limités aux apps compute-heavy, sur Chrome/Edge, avec les bons headers.
Si votre app Flutter web est un back-office Chrome, la migration est pertinente cette semaine. Si c'est une app publique, testez d'abord. Si vous n'avez pas d'app Flutter web, cette semaine ne vous concerne pas.
30 minutes suffisent pour un verdict : flutter build web → lire les warnings → flutter build web --wasm → DevTools comparison. Si le gain est < 10 %, Wasm n'est pas votre priorité.
Audit gratuit de votre code Flutter
30 min — on ouvre votre repo, on vérifie la compatibilité Wasm, les dépendances dart:html, et les headers de votre hébergeur. Sans engagement.
Références : Flutter WebAssembly Week (flutter.dev/blog) · Flutter Wasm docs (docs.flutter.dev) · Flutter Studio benchmarks (flutterstudio.dev) · FluxBoard demo (GitHub) · flutter-wasm-compare (GitHub)
Étiquettes
FAQ
Flutter web Wasm est-il prêt pour la production en 2026 ?
Oui, avec des réserves. Le WasmGC est stabilisé depuis Flutter 3.22 (mai 2024). Le blog Flutter du 17 août 2026 rapporte que 58 % des apps Flutter web existantes compilent en Wasm sans changement de code. Chrome 119+ supporte WasmGC. Firefox 120+ le déclare stable mais un bug empêche le rendu Flutter. Safari supporte WasmGC mais un bug similaire bloque Flutter. Tous les navigateurs iOS utilisent WebKit et ne supportent pas WasmGC. Le fallback JS est toujours inclus.
Faut-il des headers COOP/COEP pour Flutter web Wasm ?
Oui, pour le rendu multithread via skwasm. Sans COEP credentialless et COOP same-origin, Flutter fonctionne en single-thread. La perf reste meilleure que dart2js mais vous perdez le raster parallèle sur Web Worker. Vérifiez avec les DevTools Chrome.
Le bundle Wasm est-il plus petit que le bundle JS ?
Non. Le build --wasm produit main.dart.wasm ET main.dart.js (fallback). Le bundle total fait environ 5 % de plus comprimé (+200 à 500 ko). Le gain est dans l'exécution (25 à 40 %), pas dans la taille.
Par quoi commencer si mon équipe a une app Flutter web ?
1) flutter upgrade vers 3.47+. 2) flutter build web sans --wasm pour les warnings. 3) Corriger dart:html vers package:web. 4) flutter build web --wasm en staging. 5) Configurer COOP/COEP. 6) Mesurer avec DevTools Chrome. 7) Si gain > 20 % shippez, sinon restez en JS.
Votre site prend-il des rendez-vous — ou il présente ?
On ouvre votre URL ensemble, on pointe les 3 fuites, on vous dit si une optimisation suffit ou s’il faut refondre.
- 30 min
- Sans engagement
- Plan d’action

William Aklamavo
Expert en développement web et automatisation, passionné par l'innovation technologique et l'entrepreneuriat digital.
