spinny:~/writing $ vim webassembly-wasm-complete-guide.md
1~2WebAssembly (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.3~4Chrome 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.5~6Ce guide couvre tout ce que vous devez savoir pour commencer a developper avec WebAssembly.7~8## Qu'est-ce que WebAssembly ?9~10WebAssembly 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.11~12```mermaid13graph LR14 Rust[Rust / C / C++] --> Compiler[Compiler]15 Compiler --> WASM[.wasm Binary]16 WASM --> Browser[Browser V8/SpiderMonkey]17 WASM --> Server[Server Wasmtime]18 WASM --> Edge[Edge Cloudflare Workers]19 WASM --> Embedded[Embedded WAMR]20```21~22### Comment ca fonctionne23~24WASM 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.25~26Caracteristiques cles :27~28- **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.29- **Memoire lineaire** : un seul `ArrayBuffer` contigu partage entre WASM et l'hote. Les donnees complexes (chaines, structures) sont transmises en ecrivant en memoire et en partageant un pointeur.30- **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.31- **Portable** : le meme binaire `.wasm` s'execute sur toute plateforme disposant d'un runtime WASM, sans recompilation.32~33### WASM vs JavaScript34~35WASM ne remplace pas JavaScript. Il le complete.36~37| Aspect | JavaScript | WebAssembly |38|--------|-----------|-------------|39| **Parsing** | Parsing + compilation a l'execution | Binaire pre-compile, decodage uniquement |40| **Vitesse d'execution** | Optimise JIT, variable | Quasi natif, constant |41| **Demarrage** | Rapide pour les petits scripts | Decodage rapide, previsible |42| **Acces au DOM** | Direct | Indirect (via du glue JS) |43| **Ideal pour** | UI, manipulation du DOM, gestion des evenements | Calcul intensif sur le CPU |44| **Garbage collection** | Integre | WasmGC (nouveau), ou manuel |45~46Utilisez 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.47~48## WASM 3.0 : les nouveautes49~50WebAssembly 3.0 est devenu un standard W3C en septembre 2025, standardisant neuf fonctionnalites en developpement depuis des annees.51~52| Fonctionnalite | Ce qu'elle permet |53|----------------|-------------------|54| **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+. |55| **Exception Handling** | `try`/`catch` natifs dans WASM. Auparavant, les exceptions necessitaient des allers-retours couteux vers JavaScript. |56| **Tail Calls** | Permet une recursion efficace sans stack overflow. Essentiel pour les langages fonctionnels. |57| **Relaxed SIMD** | Instructions vectorielles 128 bits pour le traitement parallele des donnees. Permet des optimisations specifiques au materiel. |58| **Memory64** | Depasse la limite de 4 Go de memoire lineaire. Necessaire pour le traitement de donnees a grande echelle. |59| **Multi-memory** | Plusieurs regions de memoire independantes dans un seul module. |60~61La 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.62~63## WASI : WebAssembly au-dela du navigateur64~65WASM 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.66~67```mermaid68graph TD69 subgraph "Browser"70 B[WASM Module] --> Web[Web APIs\nDOM, Fetch, Canvas]71 end72~73 subgraph "Server / Edge / Embedded"74 S[WASM Module] --> WASI[WASI Interfaces]75 WASI --> FS[wasi:filesystem]76 WASI --> Net[wasi:sockets]77 WASI --> HTTP[wasi:http]78 WASI --> Clock[wasi:clocks]79 WASI --> Rand[wasi:random]80 end81```82~83WASI Preview 2 (la version stable actuelle) definit ces interfaces :84~85- `wasi:filesystem` - operations sur les fichiers via des handles de capacite (pas les descripteurs de fichiers traditionnels)86- `wasi:sockets` - reseau TCP/UDP87- `wasi:http` - gestion des requetes/reponses HTTP88- `wasi:clocks` - horloge systeme, horloge monotone89- `wasi:random` - aleatoire cryptographique90- `wasi:cli` - arguments de ligne de commande, variables d'environnement, stdio91~92Le 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.93~94### Le chemin vers WASI 1.095~96WASI 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.97~98## Le Component Model99~100Les 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.101~102### WIT (WebAssembly Interface Types)103~104WIT 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`.105~106```wit107// calculator.wit108package myorg:calculator@1.0.0;109~110interface operations {111 record calculation {112 expression: string,113 result: f64,114 timestamp: u64,115 }116~117 add: func(a: f64, b: f64) -> f64;118 multiply: func(a: f64, b: f64) -> f64;119 history: func() -> list<calculation>;120}121~122world calculator {123 export operations;124}125```126~127Les 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.128~129## Construire votre premier module WASM avec Rust130~131Rust possede les outils WASM les plus matures. Construisons un exemple pratique : un module de traitement d'images qui s'execute dans le navigateur.132~133### Configuration134~135```bash136# Install the WASM target for Rust137rustup target add wasm32-unknown-unknown138~139# Install wasm-pack (builds Rust to WASM + generates JS bindings)140cargo install wasm-pack141~142# Create a new library project143cargo new --lib image-processor144cd image-processor145```146~147### Configurer Cargo.toml148~149```toml150[package]151name = "image-processor"152version = "0.1.0"153edition = "2021"154~155[lib]156crate-type = ["cdylib"]157~158[dependencies]159wasm-bindgen = "0.2"160```161~162### Ecrire le code Rust163~164```rust165// src/lib.rs166use wasm_bindgen::prelude::*;167~168/// Convert an image buffer to grayscale.169/// Input: RGBA pixel data as a flat u8 array (4 bytes per pixel).170/// Output: Modified in place for zero-copy performance.171#[wasm_bindgen]172pub fn grayscale(pixels: &mut [u8]) {173 for chunk in pixels.chunks_exact_mut(4) {174 let r = chunk[0] as f32;175 let g = chunk[1] as f32;176 let b = chunk[2] as f32;177 // ITU-R BT.709 luminance coefficients178 let gray = (0.2126 * r + 0.7152 * g + 0.0722 * b) as u8;179 chunk[0] = gray;180 chunk[1] = gray;181 chunk[2] = gray;182 // chunk[3] is alpha, leave unchanged183 }184}185~186/// Adjust brightness of an image.187/// factor > 1.0 brightens, < 1.0 darkens.188#[wasm_bindgen]189pub fn adjust_brightness(pixels: &mut [u8], factor: f32) {190 for chunk in pixels.chunks_exact_mut(4) {191 chunk[0] = ((chunk[0] as f32 * factor).min(255.0)) as u8;192 chunk[1] = ((chunk[1] as f32 * factor).min(255.0)) as u8;193 chunk[2] = ((chunk[2] as f32 * factor).min(255.0)) as u8;194 }195}196~197/// Invert all colors in the image.198#[wasm_bindgen]199pub fn invert(pixels: &mut [u8]) {200 for chunk in pixels.chunks_exact_mut(4) {201 chunk[0] = 255 - chunk[0];202 chunk[1] = 255 - chunk[1];203 chunk[2] = 255 - chunk[2];204 }205}206~207/// Calculate the average brightness of an image (0-255).208#[wasm_bindgen]209pub fn average_brightness(pixels: &[u8]) -> f32 {210 let mut total: f64 = 0.0;211 let pixel_count = pixels.len() / 4;212 for chunk in pixels.chunks_exact(4) {213 let luminance = 0.2126 * chunk[0] as f64214 + 0.7152 * chunk[1] as f64215 + 0.0722 * chunk[2] as f64;216 total += luminance;217 }218 (total / pixel_count as f64) as f32219}220```221~222### Build223~224```bash225wasm-pack build --target web226```227~228Cela produit un repertoire `pkg/` contenant :229- `image_processor_bg.wasm` - le binaire WASM compile230- `image_processor.js` - code glue JavaScript avec des definitions TypeScript231- `package.json` - pret a etre publie sur npm232~233### Utilisation en JavaScript234~235```html236<!DOCTYPE html>237<html>238<head><title>WASM Image Processor</title></head>239<body>240 <canvas id="canvas" width="800" height="600"></canvas>241 <button onclick="applyGrayscale()">Grayscale</button>242 <button onclick="applyBrightness()">Brighten</button>243 <button onclick="applyInvert()">Invert</button>244~245 <script type="module">246 import init, { grayscale, adjust_brightness, invert } from "./pkg/image_processor.js";247~248 let ctx;249 let imageData;250~251 async function setup() {252 await init();253 const canvas = document.getElementById("canvas");254 ctx = canvas.getContext("2d");255~256 // Load an image onto the canvas257 const img = new Image();258 img.onload = () => {259 ctx.drawImage(img, 0, 0);260 imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);261 };262 img.src = "photo.jpg";263 }264~265 window.applyGrayscale = () => {266 grayscale(imageData.data);267 ctx.putImageData(imageData, 0, 0);268 };269~270 window.applyBrightness = () => {271 adjust_brightness(imageData.data, 1.3);272 ctx.putImageData(imageData, 0, 0);273 };274~275 window.applyInvert = () => {276 invert(imageData.data);277 ctx.putImageData(imageData, 0, 0);278 };279~280 setup();281 </script>282</body>283</html>284```285~286Le 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.287~288## Niveau inferieur : instanciation manuelle de WASM289~290Si vous ne souhaitez pas utiliser `wasm-bindgen`, vous pouvez instancier les modules WASM directement :291~292```javascript293const response = await fetch("calculator.wasm");294const { instance } = await WebAssembly.instantiateStreaming(response, {295 env: {296 // Functions the WASM module can call297 log_result: (value) => console.log("Result:", value),298 },299});300~301// Call exported functions302const { add, multiply } = instance.exports;303console.log(add(5, 3)); // 8304console.log(multiply(4, 7)); // 28305```306~307C'est utile quand vous voulez un overhead minimal et n'avez pas besoin d'une interoperabilite avancee entre les types.308~309## Performances : WASM vs JavaScript310~311Les benchmarks reels montrent des accelerations significatives pour les taches intensives en CPU :312~313| Tache | JavaScript | WASM | Acceleration |314|-------|-----------|------|--------------|315| Traitement d'image 4K | 180ms | 8ms (avec SIMD) | 22x |316| Redimensionnement d'image (4K) | 250ms | 45ms | 5,5x |317| Simulation physique (10K entites) | Images perdues | 60fps fluides | ~10x |318| Parsing JSON (charge importante) | 12ms | 3ms | 4x |319| Hashing cryptographique | 45ms | 6ms | 7,5x |320~321WASM tourne a environ 95 % de la vitesse du code natif. Les gains les plus importants proviennent de :322- Performances previsibles (pas de warmup JIT, pas de pauses GC)323- Instructions SIMD pour le traitement parallele des donnees324- Acces direct a la memoire sans interference du garbage collector325~326Ou WASM n'est PAS plus rapide : manipulation du DOM, petits calculs, taches liees a l'I/O. JavaScript est deja optimise pour cela.327~328## Cas d'utilisation en production329~330### Figma : rendu vectoriel en temps reel331~332Le 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.333~334### Adobe Photoshop sur le web335~336Adobe 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.337~338### Cloudflare Workers339~340Cloudflare 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.341~342### Google Meet343~344Le 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.345~346## Support navigateur (2026)347~348| Fonctionnalite | Chrome | Firefox | Safari | Edge |349|----------------|--------|---------|--------|------|350| Core WASM | Complet | Complet | Complet | Complet |351| Threads | Oui | Oui | Oui | Oui |352| SIMD (128 bits) | Oui | Oui | Oui | Oui |353| WasmGC | 119+ | 120+ | 18.2+ | Oui |354| Exception Handling | Oui | Oui | Oui | Oui |355| Memory64 | Oui | Oui | Partiel | Oui |356~357Tous les navigateurs majeurs supportent pleinement WASM. Les fonctionnalites les plus recentes (WasmGC, Exception Handling) ont atteint une large disponibilite.358~359## Reference des outils360~361| Outil | Fonction | Installation |362|-------|----------|--------------|363| **wasm-pack** | Compiler Rust en WASM, generer des packages npm | `cargo install wasm-pack` |364| **wasm-bindgen** | Bindings d'interoperabilite Rust/JS (utilise par wasm-pack) | Dependance dans Cargo.toml |365| **wasm-opt** | Optimisation de la taille du binaire (reduction de 50%+) | Partie de Binaryen : `brew install binaryen` |366| **wit-bindgen** | Generer des bindings a partir de fichiers WIT | `cargo install wit-bindgen-cli` |367| **Wasmtime** | Runtime WASM cote serveur (implementation de reference WASI) | `brew install wasmtime` |368| **Wasmer** | Runtime WASM alternatif avec support WASI | `curl https://get.wasmer.io -sSfL \| sh` |369| **wasm-feature-detect** | Detection des fonctionnalites du navigateur a l'execution | `npm install wasm-feature-detect` |370~371### Optimiser la taille du binaire372~373Les binaires WASM peuvent etre volumineux. Voici comment les reduire :374~375```toml376# Cargo.toml377[profile.release]378opt-level = "z" # Optimize for size379lto = true # Link-time optimization380codegen-units = 1 # Better optimization, slower compile381strip = true # Strip debug symbols382```383~384```bash385# Build in release mode386wasm-pack build --release --target web387~388# Further optimize with wasm-opt389wasm-opt -Oz pkg/image_processor_bg.wasm -o pkg/image_processor_bg.wasm390```391~392Un module WASM typique en Rust passe de 500 Ko a moins de 50 Ko avec ces optimisations.393~394## Feuille de route pour demarrer395~396```mermaid397flowchart TD398 A[Week 1: Basics] --> B[Week 2: Real Project]399 B --> C[Week 3: WASI and Server-side]400 C --> D[Month 2+: Production]401~402 A --> A1[Install Rust + wasm-pack]403 A --> A2[Build hello-world WASM module]404 A --> A3[Call WASM functions from JavaScript]405~406 B --> B1[Build image processor or game physics]407 B --> B2[Use wasm-bindgen for rich types]408 B --> B3[Benchmark against pure JS]409~410 C --> C1[Run WASM with Wasmtime]411 C --> C2[Explore WASI interfaces]412 C --> C3[Try Component Model with WIT]413~414 D --> D1[Optimize binary size]415 D --> D2[Use SIMD for parallelism]416 D --> D3[Deploy to Cloudflare Workers or browser]417```418~419## Conclusion420~421WebAssembly 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.422~423Vous 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.424~425Les 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.426~427> **Checklist pour demarrer :**428>429> - [x] Rust et wasm-pack installes430> - [x] Premier module WASM compile et fonctionnel dans le navigateur431> - [x] Interoperabilite JavaScript fonctionnelle (appel de WASM depuis JS)432> - [x] Build de release avec optimisations de taille appliquees433> - [x] Performances comparees a l'equivalent en pur JavaScript434> - [x] WASI explore avec Wasmtime pour les cas d'utilisation cote serveur435~
NORMAL · webassembly-wasm-complete-guide.md [readonly]435 lines · :q to close