Introduction à WebAssembly et son rôle dans Node.js
\n\nWebAssembly (WASM) est un format d'instructions binaires de bas niveau qui s'exécute dans une machine virtuelle avec des performances quasi natives. Dans l'écosystème Node.js, WebAssembly ouvre de nouveaux horizons : il permet d'exécuter du code écrit en C, C++, Rust ou Go, directement dans un environnement serveur. Cela est particulièrement pertinent pour les tâches nécessitant des performances élevées : traitement d'images, cryptographie, analyse de données, travail avec de grands tableaux de nombres.
\n\nDans cet article, nous allons parcourir le cycle complet de travail avec WebAssembly dans Node.js : de la compilation du code source à l'intégration du module prêt dans une application JavaScript.
\n\nConcepts de base et préparation de l'environnement
\n\nCe qu'il faut savoir avant de commencer
\nUn module WebAssembly est un fichier binaire avec l'extension .wasm. Il n'a pas accès directement au DOM ou au système de fichiers — toutes les interactions se font via des "fonctions importées" que vous fournissez depuis JavaScript. Dans Node.js, cette limitation est levée à l'aide de wrappers spéciaux.
Installation des outils
\nPour compiler du code en WASM, nous avons besoin du SDK Emscripten. Installation sur Linux/macOS :
\ngit clone https://github.com/emscripten-core/emsdk.git\ncd emsdk\n./emsdk install latest\n./emsdk activate latest\nsource ./emsdk_env.sh\n\nPour les projets Rust, utilisez wasm-pack :
npm install -g wasm-pack\n\nCréation et compilation du premier module WASM
\n\nExemple en C — fonction d'addition
\nCréons une fonction simple en C qui additionne deux nombres :
\n// math.c\n#include <emscripten.h>\n\nEMSCRIPTEN_KEEPALIVE\nint add(int a, int b) {\n return a + b;\n}\n\nEMSCRIPTEN_KEEPALIVE\nint multiply(int a, int b) {\n return a * b;\n}\n\nCompilons en WASM avec Emscripten :
\nemcc math.c -o math.js -s EXPORTED_FUNCTIONS="['_add', '_multiply']" -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME="createMathModule"\n\nEn sortie, nous obtenons deux fichiers : math.wasm et math.js — un wrapper pour le chargement.
Chargement du module dans Node.js
\nUtilisons maintenant le module en JavaScript :
\n// index.js\nconst createMathModule = require('./math.js');\n\ncreateMathModule().then(module => {\n const add = module._add;\n const multiply = module._multiply;\n\n console.log('5 + 3 =', add(5, 3)); // 8\n console.log('4 * 7 =', multiply(4, 7)); // 28\n});\n\nExécutons :
\nnode index.js\n\nTravail avec la mémoire et les types de données complexes
\n\nTransmission de chaînes et de tableaux
\nWASM ne manipule que des nombres. Pour transmettre des chaînes ou des tableaux, il faut allouer de la mémoire dans la mémoire linéaire du module. Considérons un exemple en C qui prend une chaîne et retourne sa longueur :
\n// string_ops.c\n#include <string.h>\n#include <emscripten.h>\n\nEMSCRIPTEN_KEEPALIVE\nint string_length(char* str) {\n return strlen(str);\n}\n\nEMSCRIPTEN_KEEPALIVE\nvoid to_upper(char* str) {\n for (int i = 0; str[i]; i++) {\n if (str[i] >= 'a' && str[i] <= 'z') {\n str[i] -= 32;\n }\n }\n}\n\nCompilons :
\nemcc string_ops.c -o string_ops.js -s EXPORTED_FUNCTIONS="['_string_length', '_to_upper']" -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME="createStringModule"\n\nCode JavaScript pour travailler avec la mémoire :
\nconst createStringModule = require('./string_ops.js');\n\ncreateStringModule().then(module => {\n const { _string_length, _to_upper, heap } = module;\n \n // Allouer de la mémoire pour la chaîne\n const input = "hello world";\n const ptr = module._malloc(input.length + 1);\n \n // Copier la chaîne dans la mémoire WASM\n for (let i = 0; i < input.length; i++) {\n heap[i + ptr] = input.charCodeAt(i);\n }\n heap[ptr + input.len