Pendant des années, WebAssembly a résolu un problème bien défini : exécuter du code à partir de langages compilés dans le navigateur avec des performances quasi natives. Mais il y avait une limite frustrante. Chaque module Wasm était une île. Vous pouviez compiler Rust vers Wasm, exposer des fonctions et les appeler à partir de JavaScript, mais si vous vouliez qu'un module Python communique avec un module Rust, vous deviez écrire une colle manuelle, coller du code qui sérialisait et désérialisait les données des deux côtés, tout comme un FFI de bas niveau. La promesse d'une réelle portabilité n'a pas atteint la composition.
Le modèle de composant est la pièce manquante, et avec WASI 0.2 début 2024, il a décollé et est devenu une base de production.
Le problème que le modèle de composant résout
Un module Wasm traditionnel expose et consomme des fonctions avec des types primitifs : entiers, flottants, pointeurs vers la mémoire linéaire. Il n’y a pas de notion native de chaînes, d’enregistrements ou de listes dans le marché public. Lorsque deux modules devaient échanger des données, il incombait au développeur de définir les conventions de sérialisation, de transmettre des pointeurs vers des tampons partagés et de s'assurer que les deux parties étaient d'accord sur le format.
Cela fonctionne dans une langue. Un module Rust appelant un autre Rust peut établir des conventions car les deux parties comprennent les mêmes abstractions. Dans un scénario multilingue, cet arrangement devient un code adhésif que vous écrivez, maintenez et éventuellement cassez de manière subtile.
WIT : le contrat entre les composants
La solution principale du modèle de composant est WIT, Wasm Interface Types, un IDL indépendant du langage qui décrit ce qu'un composant expose et ce qu'il doit consommer. Vous écrivez l'interface une seule fois et les outils de chaque langage génèrent automatiquement le code nécessaire pour l'implémenter ou l'appeler.
Considérez WIT comme Protobuf, mais pour la composition au sein du même processus plutôt que pour les messages sur le réseau. Le contrat décrit des fonctions avec des types riches, des chaînes, des listes, des enregistrements nommés, des résultats pouvant être des erreurs, et les outils se chargent de la traduction entre la représentation de chaque langue et le format canonique du composant.
Le résultat pratique est qu'un composant Rust qui traite des chaînes peut être appelé par un composant Python avec une logique métier, qui alimente un composant de sérialisation JavaScript. Pas de sérialisation manuelle, pas de saut de réseau, avec un code de colle généré à partir de WIT plutôt qu'écrit à la main.
WASI 0.2 et le passage à la production
WASI 0.2, publié en février 2024, a constitué une étape importante qui a fait de la composition des composants quelque chose que de vraies équipes peuvent adopter. La version précédente de WASI définissait la manière dont les modules Wasm accédaient au système d'exploitation, mais elle était antérieure au modèle de composant et utilisait l'ancien modèle de modules plats. WASI 0.2 a été réécrit au-dessus du modèle de composant : toutes les interfaces système, lecture de fichiers, réseau, horloge, caractère aléatoire, sont désormais des contrats WIT.
La conséquence concrète est qu'un composant qui dépend de WASI pour les E/S dépend d'une interface WIT standardisée, et non d'une implémentation spécifique. Le runtime peut satisfaire cette dépendance de différentes manières dans différents environnements, sur le serveur, en périphérie, dans le navigateur via polyfill, sans que le composant ait besoin d'être recompilé. La portabilité cesse d'être une aspiration et devient une propriété vérifiable.
La chaîne d'outils qui l'accompagne inclut wasmtime comme runtime de référence, wasm-tools pour la composition des composants et jco pour l'écosystème JavaScript, qui transforme les composants Wasm en modules ES natifs à partir des définitions WIT.
Qui l'utilise et où
Le scénario d’adoption le plus abouti est celui des plateformes sans serveur basées sur Wasm. Fermyon avec Spin et Fastly avec Compute traitent le modèle de composant comme une unité de déploiement native. Les développeurs écrivent des composants dans Rust, les compilent, les déploient et le runtime s'occupe de la composition avec les interfaces WASI pour HTTP, la base de données clé-valeur et d'autres services de plate-forme.
La ByteCode Alliance, le consortium qui spécifie le modèle de composant, comprend Fastly, Intel, Mozilla et Microsoft, ce qui confère au projet une stabilité institutionnelle qui manque parfois aux projets de spécification.
Ce qui n'existe pas encore en volume, ce sont les bibliothèques et les frameworks packagés nativement sous forme de composants Wasm. Vous pouvez aujourd'hui compiler beaucoup de choses en composants, mais le référentiel de composants publiés et réutilisables est petit comparé à celui des packages npm ou des caisses Rust. La composition fonctionne techniquement, mais le catalogue de pièces est encore en construction.
Ce qui n'est toujours pas résolu
Rust dispose aujourd'hui de la prise en charge la plus complète des modèles de composants. Go et Python disposent d'outils qui fonctionnent, mais la compilation de composants prenant entièrement en charge les types WIT génère toujours des frictions. Ce n'est pas un blocage, mais c'est une décision de pile qui compte : les équipes qui n'utilisent pas Rust rencontreront des aspérités.
Le débogage d'un graphe de composants polyglottes est véritablement plus difficile que le débogage d'un monolithe. Il existe des limites de langage, une isolation de mémoire entre les composants et des traces de pile qui ne franchissent pas ces limites de manière transparente. Les outils s'améliorent, mais ces types de problèmes ont tendance à apparaître tard dans le cycle de développement.
Il y a également une surcharge dans les appels croisés entre les composants. Il ne s'agit pas du coût d'un saut de réseau, mais il est mesurable par rapport aux appels au sein du même processus. Dans la plupart des cas, ce coût disparaît dans le bruit du fonctionnement réel du composant. Dans les trajets chauds à haute fréquence, la granularité de la composition doit être soigneusement réfléchie.
La décision architecturale pour ceux qui dirigent
Pour une équipe évaluant le modèle de composants aujourd'hui, la question la plus utile n'est pas « est-ce prêt ? mais "prêt pour quoi ?". Pour Rust, la réponse est oui, avec des réserves sur les outils de débogage. Pour les équipes Go ou Python, la réponse est "ça marche, mais ayez au moins un ingénieur qui connaît l'espace avant de s'engager".
Le modèle de composants résout un problème qui n'avait pas de bonne solution : composer des logiciels au-delà des frontières linguistiques sans payer le coût d'une frontière réseau. Si vous construisez une plate-forme d'extensibilité, le modèle garantit un contrat WIT vérifiable plutôt qu'un code natif sans restriction. Si vous avez des équipes dans différents langages qui doivent partager une logique de calcul lourde, les composants Wasm avec interfaces WIT sont l'alternative la plus propre disponible aujourd'hui.
Pour ceux qui ne se trouvent pas dans ces situations, connaître le modèle conceptuellement suffit pour l’instant. La décision qui a du sens en 2025 sera plus évidente en 2027, lorsque le catalogue de composants et le support linguistique auront mûri.
A lire aussi
- WebAssembly pour les dirigeants : quand la décision architecturale en vaut la peine
- WebAssembly au-delà du navigateur : la couche d'exécution universelle manquante -WebAssembly à la périphérie : Pourquoi démarrer rapidement et de manière isolée
- Edge computing : pourquoi le traitement distribué va redéfinir votre architecture
- Wasm pour plugins et sandbox : exécuter du code tiers en toute sécurité
- La croissance des recherches sur Rust et WebAssembly au Brésil : Analyse d'une tendance technologique