WebAssembly dans le développement web moderne : au-delà de JavaScript

JavaScript a été pendant plus de vingt ans le langage incontesté du web, mais l'environnement d'exécution du navigateur n'est plus monolingue. WebAssembly est devenu, sans bruit, la seconde exécution de tout navigateur moderne, et il rend possibles des choses que JavaScript seul ne peut pas assurer efficacement. Éditeurs d'images, codecs vidéo, moteurs de bases de données, moteurs de rendu 3D, environnements de langages : tout cela tourne aujourd'hui dans des onglets, compilé vers un format binaire de bas niveau qui s'exécute à une vitesse quasi native.

Ce qu'est WebAssembly et pourquoi cela compte

WebAssembly est un format binaire d'instructions de bas niveau exécuté par une machine virtuelle à pile. Il a été conçu comme cible de compilation portable pour les langages de programmation, afin de permettre le déploiement sur le web d'applications côté client comme côté serveur. Les quatre éditeurs de navigateurs — Google, Mozilla, Apple et Microsoft — ont collaboré à sa conception, et il est devenu un standard du W3C en 2019. Tous les grands navigateurs le prennent en charge depuis 2017.

Mais WebAssembly ne remplace pas JavaScript : il le complète. JavaScript reste le langage de la manipulation du DOM, de la gestion des événements et de la logique d'interface. WebAssembly prend en charge les traitements intensifs pour lesquels JavaScript n'a jamais été conçu. Les deux environnements cohabitent dans le même onglet : les modules importent des fonctions JavaScript, et JavaScript appelle les exports Wasm via une API bien définie.

WebAssembly ne cherche pas à remplacer JavaScript. Il cherche à résoudre les problèmes que JavaScript ne peut pas résoudre efficacement. La plateforme web en sort renforcée, parce que les développeurs peuvent choisir le bon outil pour chaque tâche au sein d'une même application.

Les fondamentaux : format binaire et mémoire linéaire

Les modules WebAssembly utilisent un format binaire (fichiers .wasm) conçu pour une analyse rapide et une taille de transmission réduite. Ce format est compact : un module type est nettement plus petit que le JavaScript équivalent, même minifié. Il encode types, fonctions, imports, exports, déclarations de mémoire et instructions dans une représentation dense que les navigateurs valident et compilent en une seule passe linéaire.

Tout module WebAssembly fonctionne sur une machine à pile conceptuelle. Les instructions empilent des valeurs sur une pile d'évaluation et les dépilent pour effectuer des opérations. Les types de valeurs pris en charge sont i32, i64, f32 et f64 : entiers et flottants sur 32 et 64 bits. Au niveau Wasm, il n'existe ni chaînes, ni objets, ni tableaux, ni aucun autre type de haut niveau. Toute structure de données complexe doit être représentée en mémoire linéaire sous forme d'octets bruts.

La mémoire linéaire est le concept le plus important de WebAssembly. Chaque module peut déclarer un ou plusieurs blocs de mémoire contiguë et redimensionnable. Cette mémoire est un tableau plat d'octets que le module lit et écrit via des instructions de chargement et de stockage. L'hôte — l'environnement JavaScript ou l'exécution Wasm — contrôle la taille initiale et la taille maximale, et peut faire croître la mémoire en demandant des pages supplémentaires de 65 536 octets chacune. Côté hôte, cette mémoire est accessible comme un ArrayBuffer, ce qui signifie que JavaScript lit et écrit exactement la mémoire qu'utilise le module.

C'est ce modèle de mémoire partagée qui rend WebAssembly efficace. L'hôte et le module échangent des données sans sérialisation ni copie : ils écrivent simplement dans le même tampon. Lorsqu'une fonction Rust renvoie une chaîne à JavaScript, elle écrit les octets en mémoire linéaire et renvoie un pointeur (un décalage entier) et une longueur. JavaScript lit ces octets directement dans l'ArrayBuffer. Pas d'analyse JSON, pas de passage de messages, aucun surcoût au-delà de l'appel de fonction lui-même.

Structure du module et validation

Un module WebAssembly est composé de sections : la section des types définit les signatures de fonctions, la section des fonctions les déclare, la section de code contient le bytecode, la section de mémoire définit la mémoire linéaire et la section d'exports met fonctions et mémoire à disposition de l'hôte. Avant toute exécution, le navigateur valide le module structurellement et impose la sûreté de typage. Cette validation garantit que tous les opérandes correspondent aux types attendus, que tous les appels référencent des signatures valides et que tous les accès mémoire restent dans les bornes déclarées. Elle prend quelques millisecondes et garantit qu'un module malformé ne peut pas détourner l'exécution.

Le modèle de sécurité est explicite et contraint. Un module WebAssembly ne peut ni accéder au DOM, ni faire de requêtes réseau, ni lire de fichiers, ni interagir avec le système, sauf si l'hôte lui fournit explicitement ces capacités via des fonctions importées. Le module s'exécute dans un bac à sable, sans accès à quoi que ce soit en dehors de sa mémoire linéaire et de sa table de fonctions importées. Cela rend sûre l'exécution de modules issus de sources non fiables — une propriété essentielle aussi bien dans le navigateur que côté serveur.

Compiler vers Wasm : Rust, C, Go et Zig comparés

La qualité de la compilation vers WebAssembly varie beaucoup d'un langage à l'autre. Certains produisent des modules compacts et efficaces, avec très peu de surcoût. D'autres exigent un environnement d'exécution qui ajoute des mégaoctets au binaire. Le choix du langage source dépend de vos exigences de performance, de l'expérience de votre équipe et de la complexité d'intégration nécessaire.

Rust : la référence pour Wasm

Rust offre la meilleure prise en charge de WebAssembly, tous langages confondus. La chaîne d'outils wasm-pack gère de façon transparente la compilation, l'optimisation et la génération des liaisons JavaScript. Rust produit de petits binaires parce qu'il n'a ni ramasse-miettes ni environnement d'exécution lourd, et parce que son modèle de propriété s'applique naturellement à la gestion de la mémoire linéaire. Un module Rust type, avec quelques fonctions exportées, pèse entre 10 et 50 Ko après LTO et optimisation, soit l'équivalent d'un Wasm écrit à la main.

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci(n - 1) + fibonacci(n - 2),
    }
}

#[wasm_bindgen]
pub fn greet(name: &str) -> String {
    format!("Hello, {}! Wasm says hello.", name)
}

La crate wasm_bindgen génère le code de liaison JavaScript qui gère automatiquement la danse de la mémoire linéaire. Appeler fibonacci depuis JavaScript ressemble à n'importe quel autre appel. En coulisses, wasm_bindgen traduit les paramètres de type chaîne en couples pointeur-longueur, invoque la fonction Wasm et reconvertit le résultat en chaîne JavaScript. Cette couche d'abstraction coûte très peu et rend l'intégration Rust-Wasm praticable au quotidien.

C et C++ via Emscripten

Emscripten est la chaîne de compilation Wasm d'origine. Elle compile du C et du C++ en s'appuyant sur LLVM et fournit une couche de compatibilité POSIX complète qui permet de porter des applications natives existantes vers le web avec un minimum de modifications du code source. Emscripten inclut un système de fichiers virtuel, une traduction d'OpenGL vers WebGL, une émulation de pthread et un environnement JavaScript qui gère le cycle de vie du module.

Go et son backend Wasm officiel

Go prend en charge WebAssembly depuis la version 1.11 et cette prise en charge s'améliore à chaque publication. Compiler un programme Go vers Wasm est simple : on fixe GOOS=js GOARCH=wasm et on lance go build. Toutefois, la prise en charge de Go a des limites nettes face à Rust. Go embarque son environnement d'exécution (ordonnanceur de goroutines, ramasse-miettes, pile de defer) dans chaque binaire, si bien qu'un module Go minimal démarre autour de 2 Mo. C'est acceptable côté serveur, où la taille compte moins, mais rédhibitoire dans le navigateur, où les temps de téléchargement et d'analyse sont critiques.

Zig : le nouveau prétendant

Zig se présente comme un remplaçant moderne de C, avec une prise en charge de WebAssembly de premier ordre. Son compilateur peut viser Wasm directement, sans passer par un enrobage comme Emscripten. Zig produit des modules comparables à ceux de Rust en taille et en performance, et sa fonctionnalité comptime permet une métaprogrammation capable de supprimer totalement le surcoût à l'exécution. Zig n'embarque aucun environnement caché — ni ramasse-miettes, ni allocateur, ni code de démarrage — sauf si vous en liez un explicitement.

  • Rust produit les plus petits binaires Wasm (10 à 50 Ko pour des modules types) et dispose du meilleur écosystème d'outils avec wasm-pack et wasm-bindgen.
  • C et C++ via Emscripten sont le meilleur choix pour porter des bases de code natives existantes : compatibilité maximale, mais binaires plus volumineux.
  • Go se compile facilement vers Wasm mais produit de gros binaires (plus de 2 Mo) à cause de l'environnement embarqué, ce qui le destine plutôt au Wasm côté serveur.
  • Zig produit des modules compacts, sans surcoût d'exécution, et convient idéalement aux usages Wasm embarqués et minimalistes.

Utiliser Wasm dans le navigateur

Charger et exécuter un module WebAssembly dans le navigateur suit une API standard, identique sur tous les navigateurs modernes. L'API JavaScript expose dans l'espace de noms WebAssembly les fonctions compile, instantiate et instantiateStreaming. La variante en flux est préférable, car elle commence à compiler pendant le téléchargement des octets et fait ainsi chevaucher les entrées-sorties réseau et la compilation.

async function loadWasm(url: string) {
  const response = await fetch(url);
  const results = await WebAssembly.instantiateStreaming(response);
  return results.instance.exports;
}

async function main() {
  const wasm = await loadWasm("/fibonacci.wasm");
  console.log(wasm.fibonacci(40));
}

main().catch(console.error);

instantiateStreaming renvoie un objet contenant une propriété instance (l'instance compilée du module) et un objet exports regroupant toutes les fonctions et la mémoire déclarées en export. Vous pouvez aussi passer un objet imports en second argument, qui donne au module accès aux fonctions et valeurs JavaScript qu'il s'attendait à trouver lors de sa compilation.

En production, on précompile généralement le module lors de l'étape de construction, ou l'on utilise un greffon d'empaqueteur. Webpack 5 gère nativement les imports Wasm et Vite propose une prise en charge expérimentale. Ces empaqueteurs se chargent automatiquement du téléchargement, de l'instanciation et du cycle de vie, ce qui permet d'importer un module Wasm comme un module JavaScript. Avec wasm-pack, le motif d'import s'écrit import init from './pkg/fibonacci.js' et fournit une fonction d'initialisation à base de promesse qui prend en charge tout le code de liaison.

Un point critique dans le navigateur est la compilation initiale. Les modules sont compilés du format binaire vers du code natif au premier chargement. Pour de petits modules, cela prend quelques millisecondes. Pour de gros modules — au-delà de 10 Mo — cela peut prendre plusieurs centaines de millisecondes et bloquer le fil principal. La solution consiste à utiliser WebAssembly.compileStreaming dans un Web Worker : la compilation se fait hors du fil principal et renvoie un objet de module compilé que le fil principal peut instancier instantanément. Ce motif est indispensable pour les applications chargeant de gros modules.

WASI et Wasm côté serveur

WebAssembly a d'abord été conçu exclusivement pour le navigateur, mais son modèle de sécurité et ses caractéristiques de performance le rendent tout aussi attrayant côté serveur. La difficulté tient à ce que le navigateur fournit des API hôtes spécifiques — DOM, fetch, WebSocket — absentes des environnements serveur. La WebAssembly System Interface règle cela en définissant un ensemble standard d'appels système de type POSIX utilisables hors du navigateur.

WASI fournit des abstractions pour les entrées-sorties fichier, le réseau, l'accès à l'horloge, la génération de nombres aléatoires, les variables d'environnement et les arguments de ligne de commande. Un module compilé avec la prise en charge de WASI peut lire des fichiers, ouvrir des sockets réseau et dialoguer avec le système d'exploitation via une interface normalisée qui fonctionne sur toute exécution conforme. C'est le socle qui permet de faire tourner Wasm comme application serveur.

Le standard WASI évolue par instantanés successifs. WASI preview 1 est la base stable prise en charge aujourd'hui par la plupart des chaînes d'outils. WASI preview 2 introduit une conception alignée sur le modèle de composants, avec une sécurité fondée sur les capacités : chaque module déclare explicitement les ressources système dont il a besoin. Preview 2 est une avancée architecturale importante car elle rend possibles des permissions à granularité fine — un module qui ne doit lire qu'un fichier précis ne peut atteindre aucun autre fichier du système.

WASI fait passer WebAssembly du statut de technologie de navigateur à celui d'environnement d'exécution universel et cloisonné. Le module qui tourne dans un onglet peut tourner aussi dans une exécution Wasm côté serveur, dans une fonction sans serveur ou sur un nœud de périphérie — sans modification. « Écrire une fois, exécuter partout » prend un sens nouveau quand ce partout inclut des environnements que JavaScript n'atteint pas.

Environnements d'exécution et déploiement

Exécuter WebAssembly hors du navigateur suppose une exécution Wasm côté serveur. Plusieurs environnements matures existent, avec des philosophies et des usages différents. Les trois plus importants sont Wasmtime, Wasmer et WAMR (WebAssembly Micro Runtime) pour les systèmes embarqués.

Wasmtime

Wasmtime est un environnement d'exécution autonome développé par la Bytecode Alliance, l'organisation qui porte aussi le standard WASI. Écrit en Rust, il compile les modules avec Cranelift (un générateur de code conçu spécifiquement pour Wasm) et propose des API en Rust, C, Python et d'autres langages. C'est l'environnement le plus répandu pour le Wasm côté serveur, derrière Cloudflare Workers, Fastly Compute@Edge et plusieurs autres plateformes de périphérie.

use wasmtime::*;

fn main() -> Result<()> {
    let engine = Engine::default();
    let module = Module::from_file(&engine, "hello.wasm")?;
    let mut store = Store::new(&engine, ());
    let instance = Instance::new(&mut store, &module, &[])?;

    let hello = instance
        .get_typed_func::<(), ()>(&mut store, "hello")?;
    hello.call(&mut store, ())?;

    Ok(())
}

L'API d'intégration de Wasmtime est claire et idiomatique. On crée un Engine (l'environnement de compilation), on charge un Module depuis un fichier ou des octets, on crée un Store (le contexte d'exécution qui détient la mémoire linéaire) et on instancie le module pour accéder à ses fonctions exportées. L'environnement gère lui-même la mémoire, le traitement des interruptions et le relais des appels système WASI.

Wasmer

Wasmer est un autre environnement très utilisé, qui prend en charge plusieurs moteurs de compilation : Cranelift, LLVM et Singlepass (compilation JIT rapide, avec une optimisation minimale). Wasmer propose des SDK pour Rust, C, C++, Python, Go, PHP, Ruby, Java et d'autres, ce qui le rend accessible depuis à peu près n'importe quel environnement. Il offre en outre un registre de paquets (WAPM) pour distribuer des modules Wasm, à la manière de npm.

La différence essentielle tient à ce que Wasmer met l'accent sur l'expérience développeur et la facilité d'intégration, tandis que Wasmtime privilégie la conformité au standard et la sécurité. Les deux sont d'excellents choix ; le vôtre dépendra de ce que vous valorisez : l'étendue de l'écosystème (Wasmer) ou la conformité stricte et l'historique en production (Wasmtime).

  • Wasmtime : le meilleur pour du Wasm serveur en production, conformité WASI stricte, compilateur JIT Cranelift, utilisé par Cloudflare et Fastly.
  • Wasmer : le meilleur pour intégrer Wasm dans des applications non écrites en Rust, prend en charge la compilation LLVM pour une vitesse quasi native, avec l'écosystème de paquets WAPM.
  • WAMR : le meilleur pour l'IoT et l'embarqué, empreinte minuscule, modes interpréteur et JIT, avec l'outil en ligne de commande iwasm.

Performances : quand Wasm l'emporte

L'avantage de performance de WebAssembly sur JavaScript dépend de la charge de travail. Pour les opérations liées au processeur et intensives en calcul, Wasm tourne généralement 1,5 à 3 fois plus vite. Pour les opérations intensives en mémoire, comme le traitement d'images ou la compression, l'écart peut être plus large parce que Wasm maîtrise directement l'agencement de la mémoire et les schémas d'allocation. Pour des charges dominées par les entrées-sorties ou par le DOM, Wasm n'apporte aucun avantage et peut même coûter davantage à cause du pont entre le module et l'hôte JavaScript.

Le modèle de compilation joue également. JavaScript recourt à la compilation JIT : le code s'exécute immédiatement, puis les chemins chauds sont optimisés au fil du temps. Wasm est compilé à l'avance ou au chargement du module et atteint donc son plein régime tout de suite : il n'y a pas de phase de chauffe. Pour des fonctions de courte durée ou des exécutions uniques, cela supprime le délai de chauffe du JIT qui peut rendre JavaScript plus lent au premier appel.

C'est sur la prévisibilité que Wasm excelle vraiment. L'optimisation JIT de JavaScript n'est pas déterministe : la même fonction peut être optimisée ou désoptimisée selon les types reçus, le nombre d'appels et l'état des heuristiques du compilateur. L'exécution Wasm, elle, est déterministe. Chaque instruction a un coût fixe. Pas de pause de ramasse-miettes, pas de confusion de types, pas d'abandon d'optimisation. Wasm est donc le bon choix quand la régularité de la latence compte plus que le débit maximal théorique : traitement audio, simulation physique, calculs financiers.

  • Wasm l'emporte pour : traitement d'images et de vidéos, synthèse et analyse audio, compression et décompression de données, opérations cryptographiques, moteurs de jeu, simulations physiques, exécution de requêtes de base de données.
  • JavaScript l'emporte pour : manipulation du DOM, gestion des événements, orchestration des requêtes réseau, rendu d'interface avec des frameworks, traitement de chaînes et de texte, petits utilitaires rarement appelés.
  • La frontière bouge : à mesure que Wasm accède aux API web via WASI et le modèle de composants, davantage de charges migrent vers Wasm, mais JavaScript reste la couche d'interface principale.

Le modèle de composants et l'avenir de Wasm

Le modèle de composants de WebAssembly est l'évolution la plus importante depuis la version initiale. Il corrige la limite fondamentale du premier Wasm : des modules isolés, sans moyen normalisé de s'interfacer entre eux. Le modèle de composants introduit un système d'interfaces de haut niveau, indépendant du langage, qui permet d'assembler les modules comme des briques.

Dans le modèle actuel, un module exporte des fonctions qui n'acceptent et ne renvoient que des entiers et des flottants. Si un module doit transmettre une chaîne, un tableau ou une structure complexe à un autre, les deux doivent s'accorder sur une convention d'agencement mémoire : partager une région de mémoire linéaire et coordonner allocation et libération. C'est fragile et propre à chaque langage. Le modèle de composants règle cela avec un système normalisé de types d'interface qui gère chaînes, enregistrements, variantes, listes et structures imbriquées au travers des frontières de modules.

Les types d'interface décrivent, indépendamment du langage, les données qui circulent entre composants. Un composant peut exporter une fonction qui prend une chaîne et renvoie un enregistrement de deux champs entiers, et n'importe quel autre composant — écrit en Rust, en C ou en Go — peut l'appeler sans rien connaître de l'agencement mémoire interne de son interlocuteur. L'environnement d'exécution produit automatiquement la logique d'adaptation et traduit entre la représentation de l'appelant et celle de l'appelé.

Études de cas réelles

WebAssembly n'est pas une technologie théorique. Il fait tourner certaines des applications web les plus exigeantes en production, et son adoption s'accélère à mesure que l'outillage mûrit et que les gains de performance deviennent indiscutables.

Figma : le pionnier de Wasm

Figma est le cas de réussite le plus connu. Son moteur de rendu est écrit en C++ et compilé vers Wasm avec Emscripten. Figma compile l'ensemble de sa base de code C++ — y compris la bibliothèque graphique Skia, le moteur de mise en forme de texte HarfBuzz et son moteur de disposition maison — en un module Wasm. La couche JavaScript gère les événements d'entrée et le DOM, tandis que Wasm assure tout le rendu, la détection de clics et les calculs de disposition. Résultat : un outil de conception qui tourne dans un onglet avec des performances rivalisant avec celles d'une application de bureau native.

SQLite : une base de données dans le navigateur

SQLite est probablement le module Wasm le plus déployé au monde. Le projet publie une version Wasm officielle qui exécute le moteur complet dans le navigateur. Les utilisateurs peuvent interroger une base entièrement côté client, sans aucun composant serveur. Cette version est produite avec Emscripten et inclut un système de fichiers virtuel permettant de conserver les bases dans IndexedDB.

Les conséquences sont considérables. Les applications nécessitant des capacités d'interrogation côté client — outils d'analyse, tableaux de bord de reporting, carnets de calcul scientifique — peuvent utiliser SQLite en Wasm pour exécuter des agrégations complexes, des jointures et des fonctions de fenêtrage directement dans le navigateur, sans envoyer de données à un serveur. Des bibliothèques comme sql.js et better-sqlite3-wasm enveloppent le module dans des API JavaScript propres et le rendent aussi simple à utiliser que n'importe quel paquet npm.

Google Earth : Wasm pour le rendu 3D

Google Earth pour navigateurs a été reconstruit avec Wasm pour ses chaînes de traitement du terrain 3D et de décompression de données. Pendant que l'utilisateur navigue, le module reçoit des données binaires compressées, les décompresse à l'aide d'algorithmes C++ optimisés compilés vers Wasm, transforme la géométrie en maillages affichables et transmet le résultat à WebGL — le tout dans le budget d'une seule image d'animation et sans aucun coût de copie de données.

  • Figma utilise Wasm pour son moteur de rendu C++ et atteint des performances de classe native pour l'édition de graphismes vectoriels dans le navigateur.
  • SQLite publie une version Wasm officielle qui exécute le moteur complet côté client et permet des requêtes hors ligne sans serveur.
  • Google Earth s'appuie sur Wasm pour la décompression en temps réel et le traitement géométrique de données géospatiales en flux à 60 images par seconde.
  • Adobe utilise Wasm dans Photoshop pour le web (via du code C++ compilé avec Emscripten) pour les filtres d'image et les conversions d'espaces colorimétriques.
  • Zoom utilise Wasm dans son client web pour le décodage vidéo et le floutage d'arrière-plan.

Wasm en périphérie et en sans-serveur

Les plateformes sans serveur ont adopté WebAssembly comme environnement d'exécution en périphérie en raison de son avantage au démarrage à froid face aux conteneurs. Un module Wasm démarre en microsecondes — et non en millisecondes — parce qu'il n'y a pas de système d'exploitation à amorcer, pas de processus à dupliquer, pas d'environnement à initialiser. Là où la latence de démarrage à froid pèse directement sur l'expérience utilisateur, c'est un changement de nature.

Cloudflare Workers a été la première grande plateforme à adopter Wasm. Les Workers s'exécutent dans des isolats V8 capables d'exécuter à la fois du JavaScript et des modules Wasm. Un Worker qui confie sa logique de calcul à un module peut commencer à répondre en moins de 5 millisecondes depuis un démarrage à froid. L'environnement fournit un ensemble limité d'API fondées sur la spécification Service Worker — fetch, Cache, stockage KV et Durable Objects — et les modules compilés avec WASI peuvent les utiliser via le mécanisme d'import de l'hôte.

Compute@Edge de Fastly utilise Wasmtime comme environnement principal et exige que tout calcul soit compilé vers Wasm. Les développeurs écrivent leur logique en Rust, Go ou JavaScript (que Fastly compile à l'avance vers Wasm), et le module obtenu s'exécute sur les nœuds de périphérie de Fastly. Ce modèle offre un isolement de sécurité solide — chaque requête s'exécute dans une instance neuve, sans état partagé — associé à la vitesse de démarrage qui rend le calcul en périphérie praticable.

L'écosystème Wasm en périphérie est encore jeune, mais il croît vite. Des plateformes comme Fermyon Spin et Deislabs proposent des cadres pensés spécifiquement pour bâtir des applications sans serveur en Wasm. Ils masquent les détails de WASI et offrent des motifs familiers — gestionnaires HTTP, stockage clé-valeur, tâches planifiées — tout en exécutant l'ensemble via Wasm. La promesse : écrire sa logique métier une fois, dans n'importe quel langage compilant vers Wasm, et la déployer sans modification sur toute plateforme compatible WASI.

Se lancer avec Wasm aujourd'hui

La meilleure façon de commencer dépend de votre objectif. Pour utiliser Wasm dans le navigateur, le chemin le plus rapide est Rust avec wasm-pack. Installez Rust, ajoutez la cible wasm32-unknown-unknown et créez un projet avec wasm-pack new. Le projet généré contient un exemple fonctionnel avec une fonction Wasm appelable depuis JavaScript, un script de construction qui produit un paquet compatible npm et un harnais de tests qui exécute votre module dans un navigateur sans interface.

Pour explorer le Wasm côté serveur, commencez par Wasmtime et son outil en ligne de commande. Installez wasmtime, compilez n'importe quel programme C ou Rust avec la prise en charge de WASI et exécutez-le avec wasmtime programme.wasm. Vous constaterez qu'un programme en ligne de commande compilé vers Wasm se comporte comme un binaire natif : il lit l'entrée standard, écrit sur la sortie standard, accède aux fichiers et se termine avec un code de statut. L'expérience est étonnamment fluide.

Pour expérimenter en périphérie et en sans-serveur, Cloudflare Workers propose une offre gratuite compatible Wasm. Écrivez une fonction en Rust, compilez-la vers Wasm et déployez-la sur le réseau mondial de Cloudflare. Vous verrez des temps de réponse inférieurs à 10 millisecondes depuis la plupart des régions, et vous constaterez directement comment Wasm évacue la question du démarrage à froid.

Le premier pas le plus pratique avec Wasm n'est pas de réécrire toute votre application. Trouvez une fonction coûteuse en calcul — un filtre, une transformation, une validation —, réécrivez-la en Rust, compilez-la vers Wasm et intégrez-la à votre base de code existante. Mesurez l'écart. Quand vous verrez un gain d'un facteur trois pour cinquante lignes de Wasm, vous comprendrez pourquoi cette technologie compte.

Le paysage des outils progresse vite. wasm-pack, cargo-generate et wasm-tools offrent un flux de développement mature. La chaîne Binaryen fournit wasm-opt pour optimiser les modules et réduire leur taille de 20 à 30 pour cent. Wasmtime et Wasmer continuent de combler l'écart avec l'exécution native. Et le modèle de composants rendra bientôt les modules interopérables d'une manière impossible aux débuts de Wasm.

WebAssembly ne remplace pas le web tel que nous le connaissons : il enrichit la plateforme, avec une seconde exécution qui fait ce que JavaScript ne peut pas faire. La prochaine fois que vous affronterez un problème de performance où vous aurez l'impression de lutter contre la nature dynamique de JavaScript, demandez-vous si la partie lourde en calcul pourrait être extraite dans un module Wasm. Les outils sont prêts pour la production, le gain est réel, et l'avenir de Wasm — avec le modèle de composants, WASI preview 2 et un meilleur soutien des langages — ne fait que s'améliorer.

La plateforme web a été conçue pour être extensible. WebAssembly en est l'extension la plus importante depuis dix ans. La comprendre n'est pas optionnel pour qui veut bâtir des applications qui repoussent les limites de ce que le web sait faire.

See what your own repository can account for.

Thirty minutes on a repository you choose, including the part the record cannot attribute.