WebAssembly (Wasm) promet des performances natives dans le navigateur. Après l’avoir utilisé en production sur plusieurs projets, voici ce qui fonctionne vraiment et ce qui relève du marketing.
WebAssembly en 2 minutes
Qu’est-ce que c’est ?
WebAssembly est un format binaire exécutable dans les navigateurs modernes, offrant des performances proches du code natif.
┌─────────────┐
│ Rust/C/C++ │
│ Go, etc. │
└──────┬──────┘
│ Compile
┌──────▼──────┐
│ .wasm │ ← Binaire compact
└──────┬──────┘
│ Load
┌──────▼──────┐
│ Browser │ ← Exécution rapide
└─────────────┘
Promesses marketing vs Réalité
Marketing : “Wasm est 20x plus rapide que JavaScript !”
Réalité : Dépend totalement du cas d’usage.
Cas d’usage où Wasm excelle
1. Calculs intensifs
Exemple : Traitement d’image
// Rust compilé en Wasm
#[wasm_bindgen]
pub fn apply_filter(pixels: &mut [u8], width: u32, height: u32) {
for y in 0..height {
for x in 0..width {
let idx = (y * width + x) * 4;
// Algorithme gourmand en CPU
pixels[idx] = compute_pixel(pixels[idx]);
}
}
}
Résultat mesuré :
- JavaScript : 450ms
- Wasm : 85ms
- Gain : 5.3x
2. Portage d’applications existantes
Cas réel : Porter un éditeur vidéo C++ vers le web.
Avant :
- Réécrire en JavaScript : 6 mois + bugs
- Performance dégradée
Avec Wasm :
- Compilation directe : 2 semaines
- Performance proche du natif
- Code existant réutilisé
Exemples célèbres :
- Figma (éditeur graphique)
- AutoCAD Web
- Google Earth
3. Bibliothèques de compression
// Bibliothèque de compression Wasm
import { compress } from './wasm-compress';
// 3x plus rapide que zlib JavaScript
const compressed = await compress(largeData);
Use cases :
- Compression vidéo/audio
- Encodage/décodage images
- Cryptographie
Quand NE PAS utiliser Wasm
1. DOM manipulation
// ❌ Wasm n'a pas accès direct au DOM
// Doit passer par JavaScript (overhead)
// JavaScript reste KING pour ça :
document.querySelector('.button').addEventListener('click', () => {
// Wasm serait plus lent ici !
});
2. Applications “business logic” simples
// ❌ Pas besoin de Wasm pour ça
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
// JavaScript est amplement suffisant
3. I/O intensive
Wasm n’accélère pas :
- Requêtes HTTP
- Accès BDD
- Lecture fichiers
Le bottleneck est ailleurs.
Performance : Benchmarks réels
Test 1 : Calcul Fibonacci (CPU-bound)
// JavaScript
function fib(n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}
// Résultats fib(40) :
// JavaScript : 1250ms
// Wasm : 680ms
// Gain : 1.8x
Test 2 : Parsing JSON (I/O-bound)
// Résultats parsing 10MB JSON :
// JavaScript : 85ms
// Wasm : 82ms
// Gain : 1.04x (négligeable)
Conclusion : Wasm brille sur CPU-bound, pas I/O-bound.
Stack technique : Rust → Wasm
Setup projet
# Installer wasm-pack
cargo install wasm-pack
# Créer projet
cargo new --lib my-wasm-lib
cd my-wasm-lib
Code Rust
// src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn heavy_computation(data: Vec<u8>) -> Vec<u8> {
// Traitement intensif
data.iter()
.map(|&x| complex_algo(x))
.collect()
}
fn complex_algo(n: u8) -> u8 {
// Algorithme coûteux
(0..n).fold(0, |acc, x| acc ^ x)
}
Build et intégration
# Compiler en Wasm
wasm-pack build --target web
# Génère :
# pkg/
# my_wasm_lib_bg.wasm
# my_wasm_lib.js
// app.js
import init, { heavy_computation } from './pkg/my_wasm_lib.js';
async function main() {
await init(); // Charger le module Wasm
const data = new Uint8Array([1, 2, 3, 4, 5]);
const result = heavy_computation(data);
console.log(result);
}
main();
Optimisation : Taille bundle
Problème : Wasm peut être lourd
my_wasm_lib_bg.wasm : 287KB
my_wasm_lib.js : 12KB
Total : 299KB
Optimisation 1 : wasm-opt
# Installer binaryen
npm install -g binaryen
# Optimiser
wasm-opt -Oz -o optimized.wasm input.wasm
# Résultat : 287KB → 156KB (-45%)
Optimisation 2 : Lazy loading
// Ne charger Wasm que si nécessaire
button.addEventListener('click', async () => {
const { heavy_computation } = await import('./pkg/my_wasm_lib.js');
// Wasm chargé seulement au clic
});
Optimisation 3 : Streaming compilation
// Compilation en streaming (plus rapide)
const { instance } = await WebAssembly.instantiateStreaming(
fetch('optimized.wasm')
);
Production : Nos retours d’expérience
Projet 1 : Éditeur de PDF web
Contexte :
- Manipulation PDF côté client
- Rotation, fusion, compression pages
Stack :
- Rust + pdf-rs
- Compilé en Wasm
Résultats :
- Fusion 10 PDFs (50 pages) : 2.1s (vs impossible en JS pur)
- Bundle Wasm : 1.2MB (gzipped)
- Satisfaction users : 9.2/10
Projet 2 : Plateforme e-learning
Contexte :
- Détection plagiat côté client
- Algorithme Levenshtein distance sur gros textes
Stack :
- AssemblyScript → Wasm
Résultats :
- Comparaison 2000 mots : 145ms (vs 890ms JS)
- Gain : 6.1x
- ROI dev : 2 semaines
Debugging Wasm : Les outils
1. Chrome DevTools
Sources → WebAssembly
- Voir le bytecode Wasm
- Breakpoints
- Call stack
2. wasm-sourcemap
# Générer sourcemaps
wasm-pack build --debug
# Debugger le code Rust dans Chrome !
3. Console logging
// Rust
use web_sys::console;
#[wasm_bindgen]
pub fn debug_func() {
console::log_1(&"Debug from Wasm!".into());
}
Futur : Wasm Component Model
Ce qui arrive en 2025-2026 :
Component Model : Wasm modules composables
- Interopérabilité entre langages
- Standard d'import/export
- Écosystème de composants réutilisables
Exemple (futur) :
// Composer modules Wasm de différentes sources
import { image_filter } from 'wasm:image-processing';
import { compress } from 'wasm:compression';
const filtered = image_filter(image);
const compressed = compress(filtered);
Checklist décision
Utilisez Wasm si :
✅ Calculs CPU-intensifs (>100ms en JS) ✅ Portage code existant (C/C++/Rust) ✅ Performance critique mesurée ✅ Bibliothèque spécialisée disponible
Restez sur JavaScript si :
❌ DOM manipulation ❌ I/O-bound (HTTP, DB) ❌ Logique métier simple ❌ Pas de besoin perf critique
Ressources
Outils
- wasm-pack - Rust → Wasm
- AssemblyScript - TypeScript → Wasm
- Emscripten - C/C++ → Wasm
Learning
Conclusion
WebAssembly n’est pas un remplacement de JavaScript.
C’est un complément pour des cas d’usage spécifiques :
- Calculs intensifs
- Portage d’applications
- Performance critique
Approche pragmatique :
- Mesurer le problème réel
- Tester avec Wasm sur un POC
- Comparer les métriques
- Décider avec data
En 2025, Wasm est mature pour la production. Mais utilisez-le uniquement quand il apporte une vraie valeur.
Et vous, avez-vous des use cases Wasm ? Partagez !