WebAssembly (WASM) a commence comme un moyen d'executer du C++ dans le navigateur. En 2026, il s'execute partout - navigateurs, serveurs, reseaux edge, appareils embarques - et alimente certaines des applications les plus exigeantes du web. Le moteur de rendu de Figma, Adobe Photoshop sur le web, le traitement video de Google Meet et la plateforme de calcul edge de Cloudflare fonctionnent tous sur WebAssembly.
Chrome Platform Status situe WASM a environ 5,5 % de tous les chargements de pages Chrome debut 2026, contre 4,5 % l'annee precedente. Avec WASM 3.0 devenu standard W3C et WASI en cours de maturation vers la version 1.0, l'ecosysteme a atteint un point de basculement.
Ce guide couvre tout ce que vous devez savoir pour commencer a developper avec WebAssembly.
Qu'est-ce que WebAssembly ?
WebAssembly est un format d'instructions binaires concu comme cible de compilation. Vous ecrivez du code dans un langage de haut niveau (Rust, C, C++, Go, Kotlin), le compilez en .wasm, et l'executez dans tout environnement disposant d'un runtime WASM - navigateurs, Node.js, Cloudflare Workers, Wasmtime ou Wasmer.
Comment ca fonctionne
WASM est une machine virtuelle basee sur une pile. Les fonctions empilent et depilent des valeurs sur une pile d'operandes. Le runtime hote (V8 dans Chrome, SpiderMonkey dans Firefox) compile en JIT le bytecode WASM en code machine natif, c'est pourquoi les performances sont quasi natives.
Caracteristiques cles :
- Execution en sandbox : les modules WASM ne peuvent acceder qu'aux ressources que l'hote accorde explicitement. Aucun acces au systeme de fichiers, au reseau ou au systeme d'exploitation sauf autorisation. C'est fondamentalement different du code natif.
- Memoire lineaire : un seul
ArrayBuffercontigu partage entre WASM et l'hote. Les donnees complexes (chaines, structures) sont transmises en ecrivant en memoire et en partageant un pointeur. - Types limites : WASM ne supporte nativement que quatre types :
i32,i64,f32,f64. Tout le reste (chaines, tableaux, objets) necessite un encodage via la memoire lineaire ou le Component Model. - Portable : le meme binaire
.wasms'execute sur toute plateforme disposant d'un runtime WASM, sans recompilation.
WASM vs JavaScript
WASM ne remplace pas JavaScript. Il le complete.
| Aspect | JavaScript | WebAssembly |
|---|---|---|
| Parsing | Parsing + compilation a l'execution | Binaire pre-compile, decodage uniquement |
| Vitesse d'execution | Optimise JIT, variable | Quasi natif, constant |
| Demarrage | Rapide pour les petits scripts | Decodage rapide, previsible |
| Acces au DOM | Direct | Indirect (via du glue JS) |
| Ideal pour | UI, manipulation du DOM, gestion des evenements | Calcul intensif sur le CPU |
| Garbage collection | Integre | WasmGC (nouveau), ou manuel |
Utilisez JavaScript pour l'interface utilisateur et le travail sur le DOM. Utilisez WASM pour le calcul lourd : traitement d'images, encodage video, simulations physiques, cryptographie, parsing de donnees.
WASM 3.0 : les nouveautes
WebAssembly 3.0 est devenu un standard W3C en septembre 2025, standardisant neuf fonctionnalites en developpement depuis des annees.
| Fonctionnalite | Ce qu'elle permet |
|---|---|
| WasmGC | Garbage collection native dans WASM. Les langages geres (Java, Kotlin, Dart) peuvent compiler en WASM sans embarquer leur propre runtime GC. Supporte dans Chrome 119+, Firefox 120+, Safari 18.2+. |
| Exception Handling | try/catch natifs dans WASM. Auparavant, les exceptions necessitaient des allers-retours couteux vers JavaScript. |
| Tail Calls | Permet une recursion efficace sans stack overflow. Essentiel pour les langages fonctionnels. |
| Relaxed SIMD | Instructions vectorielles 128 bits pour le traitement parallele des donnees. Permet des optimisations specifiques au materiel. |
| Memory64 | Depasse la limite de 4 Go de memoire lineaire. Necessaire pour le traitement de donnees a grande echelle. |
| Multi-memory | Plusieurs regions de memoire independantes dans un seul module. |
La plus impactante est WasmGC. Avant elle, compiler Java ou Kotlin en WASM signifiait embarquer un garbage collector complet dans le binaire, gonflant la taille des fichiers. Desormais, le GC du navigateur gere la memoire pour les modules WASM, exactement comme il le fait pour JavaScript.
WASI : WebAssembly au-dela du navigateur
WASM dans le navigateur est puissant, mais WASI (WebAssembly System Interface) est ce qui fait de WASM un runtime universel. WASI fournit des interfaces standardisees pour les ressources systeme - fichiers, reseau, horloges, nombres aleatoires - permettant aux modules WASM de fonctionner en dehors du navigateur.
WASI Preview 2 (la version stable actuelle) definit ces interfaces :
wasi:filesystem- operations sur les fichiers via des handles de capacite (pas les descripteurs de fichiers traditionnels)wasi:sockets- reseau TCP/UDPwasi:http- gestion des requetes/reponses HTTPwasi:clocks- horloge systeme, horloge monotonewasi:random- aleatoire cryptographiquewasi:cli- arguments de ligne de commande, variables d'environnement, stdio
Le principe cle est la securite basee sur les capacites : un module WASM ne peut pas acceder au systeme de fichiers a moins que l'hote n'accorde explicitement un handle vers un repertoire specifique. Cela rend WASI fondamentalement plus sur que l'execution d'executables natifs.
Le chemin vers WASI 1.0
WASI 0.3.0 (ajoutant des primitives async/concurrence) est prevu en 2026, suivi de WASI 1.0. L'ajout principal est l'async integre au langage avec un I/O en streaming a copie zero.
Le Component Model
Les modules WASM de base ne peuvent echanger que des nombres. Le Component Model resout cette limitation en ajoutant un systeme de types riche et une couche de composabilite au-dessus de WASM.
WIT (WebAssembly Interface Types)
WIT est un langage de definition d'interfaces qui permet aux composants de declarer leurs importations et exportations avec des types riches - chaines, enregistrements, listes, variantes, enumerations - pas seulement i32 et f64.
// calculator.wit package myorg:calculator@1.0.0; interface operations { record calculation { expression: string, result: f64, timestamp: u64, } add: func(a: f64, b: f64) -> f64; multiply: func(a: f64, b: f64) -> f64; history: func() -> list<calculation>; } world calculator { export operations; }
Les toolchains comme wit-bindgen generent des bindings specifiques au langage a partir des fichiers WIT. Un composant Rust et un composant Python peuvent echanger des chaines, des enregistrements et des listes via des contrats WIT sans que l'une ou l'autre partie connaisse le langage d'implementation de l'autre.
Construire votre premier module WASM avec Rust
Rust possede les outils WASM les plus matures. Construisons un exemple pratique : un module de traitement d'images qui s'execute dans le navigateur.
Configuration
# Install the WASM target for Rust rustup target add wasm32-unknown-unknown # Install wasm-pack (builds Rust to WASM + generates JS bindings) cargo install wasm-pack # Create a new library project cargo new --lib image-processor cd image-processor
Configurer Cargo.toml
[package] name = "image-processor" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] wasm-bindgen = "0.2"
Ecrire le code Rust
// src/lib.rs use wasm_bindgen::prelude::*; /// Convert an image buffer to grayscale. /// Input: RGBA pixel data as a flat u8 array (4 bytes per pixel). /// Output: Modified in place for zero-copy performance. #[wasm_bindgen] pub fn grayscale(pixels: &mut [u8]) { for chunk in pixels.chunks_exact_mut(4) { let r = chunk[0] as f32; let g = chunk[1] as f32; let b = chunk[2] as f32; // ITU-R BT.709 luminance coefficients let gray = (0.2126 * r + 0.7152 * g + 0.0722 * b) as u8; chunk[0] = gray; chunk[1] = gray; chunk[2] = gray; // chunk[3] is alpha, leave unchanged } } /// Adjust brightness of an image. /// factor > 1.0 brightens, < 1.0 darkens. #[wasm_bindgen] pub fn adjust_brightness(pixels: &mut [u8], factor: f32) { for chunk in pixels.chunks_exact_mut(4) { chunk[0] = ((chunk[0] as f32 * factor).min(255.0)) as u8; chunk[1] = ((chunk[1] as f32 * factor).min(255.0)) as u8; chunk[2] = ((chunk[2] as f32 * factor).min(255.0)) as u8; } } /// Invert all colors in the image. #[wasm_bindgen] pub fn invert(pixels: &mut [u8]) { for chunk in pixels.chunks_exact_mut(4) { chunk[0] = 255 - chunk[0]; chunk[1] = 255 - chunk[1]; chunk[2] = 255 - chunk[2]; } } /// Calculate the average brightness of an image (0-255). #[wasm_bindgen] pub fn average_brightness(pixels: &[u8]) -> f32 { let mut total: f64 = 0.0; let pixel_count = pixels.len() / 4; for chunk in pixels.chunks_exact(4) { let luminance = 0.2126 * chunk[0] as f64 + 0.7152 * chunk[1] as f64 + 0.0722 * chunk[2] as f64; total += luminance; } (total / pixel_count as f64) as f32 }
Build
wasm-pack build --target web
Cela produit un repertoire pkg/ contenant :
image_processor_bg.wasm- le binaire WASM compileimage_processor.js- code glue JavaScript avec des definitions TypeScriptpackage.json- pret a etre publie sur npm
Utilisation en JavaScript
<!DOCTYPE html> <html> <head><title>WASM Image Processor</title></head> <body> <canvas id="canvas" width="800" height="600"></canvas> <button onclick="applyGrayscale()">Grayscale</button> <button onclick="applyBrightness()">Brighten</button> <button onclick="applyInvert()">Invert</button> <script type="module"> import init, { grayscale, adjust_brightness, invert } from "./pkg/image_processor.js"; let ctx; let imageData; async function setup() { await init(); const canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); // Load an image onto the canvas const img = new Image(); img.onload = () => { ctx.drawImage(img, 0, 0); imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); }; img.src = "photo.jpg"; } window.applyGrayscale = () => { grayscale(imageData.data); ctx.putImageData(imageData, 0, 0); }; window.applyBrightness = () => { adjust_brightness(imageData.data, 1.3); ctx.putImageData(imageData, 0, 0); }; window.applyInvert = () => { invert(imageData.data); ctx.putImageData(imageData, 0, 0); }; setup(); </script> </body> </html>
Le point cle : imageData.data est un Uint8ClampedArray adosse a un ArrayBuffer. Lorsqu'il est transmis a WASM, il partage la meme memoire - aucune copie. La fonction Rust modifie les pixels directement, et le cote JavaScript voit immediatement les changements.
Niveau inferieur : instanciation manuelle de WASM
Si vous ne souhaitez pas utiliser wasm-bindgen, vous pouvez instancier les modules WASM directement :
const response = await fetch("calculator.wasm"); const { instance } = await WebAssembly.instantiateStreaming(response, { env: { // Functions the WASM module can call log_result: (value) => console.log("Result:", value), }, }); // Call exported functions const { add, multiply } = instance.exports; console.log(add(5, 3)); // 8 console.log(multiply(4, 7)); // 28
C'est utile quand vous voulez un overhead minimal et n'avez pas besoin d'une interoperabilite avancee entre les types.
Performances : WASM vs JavaScript
Les benchmarks reels montrent des accelerations significatives pour les taches intensives en CPU :
| Tache | JavaScript | WASM | Acceleration |
|---|---|---|---|
| Traitement d'image 4K | 180ms | 8ms (avec SIMD) | 22x |
| Redimensionnement d'image (4K) | 250ms | 45ms | 5,5x |
| Simulation physique (10K entites) | Images perdues | 60fps fluides | ~10x |
| Parsing JSON (charge importante) | 12ms | 3ms | 4x |
| Hashing cryptographique | 45ms | 6ms | 7,5x |
WASM tourne a environ 95 % de la vitesse du code natif. Les gains les plus importants proviennent de :
- Performances previsibles (pas de warmup JIT, pas de pauses GC)
- Instructions SIMD pour le traitement parallele des donnees
- Acces direct a la memoire sans interference du garbage collector
Ou WASM n'est PAS plus rapide : manipulation du DOM, petits calculs, taches liees a l'I/O. JavaScript est deja optimise pour cela.
Cas d'utilisation en production
Figma : rendu vectoriel en temps reel
Le moteur de rendu principal de Figma est du C++ compile en WASM. Chaque forme, degrade et effet est calcule en WASM et dessine sur un element Canvas. Cela permet a Figma de gerer des designs complexes avec des milliers de calques a 60fps dans le navigateur - des performances impossibles en pur JavaScript.
Adobe Photoshop sur le web
Adobe a porte des filtres et outils cles de Photoshop en WASM en utilisant Rust. Leurs benchmarks montrent un traitement d'images 4K en 22ms avec WASM SIMD contre 180ms en JavaScript - une amelioration de 8 fois qui rend possibles les previsualisations de filtres en temps reel.
Cloudflare Workers
Cloudflare execute des modules WASM dans des isolats V8 a travers plus de 330 emplacements edge. Les cold starts sont de 1 a 5ms (contre 100 a 500ms pour le serverless base sur des conteneurs). En fevrier 2026, ils ont deploye l'inference Llama-3-8b sur leur reseau edge en utilisant WASM.
Google Meet
Le flou d'arriere-plan et les arriere-plans virtuels dans Google Meet utilisent WASM avec SIMD pour le traitement video en temps reel. Le module WASM traite chaque image video assez rapidement pour maintenir une video fluide a 30fps.
Support navigateur (2026)
| Fonctionnalite | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| Core WASM | Complet | Complet | Complet | Complet |
| Threads | Oui | Oui | Oui | Oui |
| SIMD (128 bits) | Oui | Oui | Oui | Oui |
| WasmGC | 119+ | 120+ | 18.2+ | Oui |
| Exception Handling | Oui | Oui | Oui | Oui |
| Memory64 | Oui | Oui | Partiel | Oui |
Tous les navigateurs majeurs supportent pleinement WASM. Les fonctionnalites les plus recentes (WasmGC, Exception Handling) ont atteint une large disponibilite.
Reference des outils
| Outil | Fonction | Installation |
|---|---|---|
| wasm-pack | Compiler Rust en WASM, generer des packages npm | cargo install wasm-pack |
| wasm-bindgen | Bindings d'interoperabilite Rust/JS (utilise par wasm-pack) | Dependance dans Cargo.toml |
| wasm-opt | Optimisation de la taille du binaire (reduction de 50%+) | Partie de Binaryen : brew install binaryen |
| wit-bindgen | Generer des bindings a partir de fichiers WIT | cargo install wit-bindgen-cli |
| Wasmtime | Runtime WASM cote serveur (implementation de reference WASI) | brew install wasmtime |
| Wasmer | Runtime WASM alternatif avec support WASI | curl https://get.wasmer.io -sSfL | sh |
| wasm-feature-detect | Detection des fonctionnalites du navigateur a l'execution | npm install wasm-feature-detect |
Optimiser la taille du binaire
Les binaires WASM peuvent etre volumineux. Voici comment les reduire :
# Cargo.toml [profile.release] opt-level = "z" # Optimize for size lto = true # Link-time optimization codegen-units = 1 # Better optimization, slower compile strip = true # Strip debug symbols
# Build in release mode wasm-pack build --release --target web # Further optimize with wasm-opt wasm-opt -Oz pkg/image_processor_bg.wasm -o pkg/image_processor_bg.wasm
Un module WASM typique en Rust passe de 500 Ko a moins de 50 Ko avec ces optimisations.
Feuille de route pour demarrer
Conclusion
WebAssembly n'est plus experimental. C'est une technologie de production utilisee par certaines des applications les plus exigeantes du web. Performances quasi natives, securite en sandbox et portabilite universelle - aucune autre cible de compilation ne vous offre ces trois avantages a la fois.
Vous n'avez pas besoin de reecrire toute votre application en WASM. Commencez par une seule fonction intensive en CPU - un filtre d'image, un parser de donnees, un calcul physique - compilez-la en WASM et appelez-la depuis JavaScript. Mesurez la difference. Puis decidez ou WASM peut encore aider.
Les outils sont matures, le support des navigateurs est universel et l'ecosysteme est en pleine croissance. Si vous ecrivez du Rust, vous n'etes qu'a une commande du navigateur.
Checklist pour demarrer :
- Rust et wasm-pack installes
- Premier module WASM compile et fonctionnel dans le navigateur
- Interoperabilite JavaScript fonctionnelle (appel de WASM depuis JS)
- Build de release avec optimisations de taille appliquees
- Performances comparees a l'equivalent en pur JavaScript
- WASI explore avec Wasmtime pour les cas d'utilisation cote serveur