Introducción a WebAssembly y su papel en Node.js
\n\nWebAssembly (WASM) es un formato de instrucciones binarias de bajo nivel que se ejecuta en una máquina virtual con un rendimiento casi nativo. En el ecosistema de Node.js, WebAssembly abre nuevos horizontes: permite ejecutar código escrito en C, C++, Rust o Go directamente en el entorno del servidor. Esto es especialmente relevante para tareas que requieren alto rendimiento: procesamiento de imágenes, criptografía, análisis de datos, trabajo con grandes arreglos de números.
\n\nEn este artículo, analizaremos el ciclo completo de trabajo con WebAssembly en Node.js: desde la compilación del código fuente hasta la integración del módulo terminado en una aplicación JavaScript.
\n\nConceptos básicos y preparación del entorno
\n\nQué necesita saber antes de comenzar
\nUn módulo WebAssembly es un archivo binario con la extensión .wasm. No tiene acceso directo al DOM ni al sistema de archivos: toda la interacción se realiza a través de "funciones importadas" que usted pasa desde JavaScript. En Node.js, esta limitación se elimina mediante envoltorios especiales.
Instalación de herramientas
\nPara compilar código a WASM necesitamos el SDK de Emscripten. Instalación en 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\nPara proyectos Rust, use wasm-pack:
npm install -g wasm-pack\n\nCreación y compilación del primer módulo WASM
\n\nEjemplo en C: función de suma
\nCreemos una función simple en C que suma dos números:
\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\nCompilamos a WASM con Emscripten:
\nemcc math.c -o math.js -s EXPORTED_FUNCTIONS="['_add', '_multiply']" -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME="createMathModule"\n\nComo resultado, obtenemos dos archivos: math.wasm y math.js, un envoltorio para la carga.
Carga del módulo en Node.js
\nAhora usamos el módulo 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\nEjecutamos:
\nnode index.js\n\nTrabajo con memoria y tipos de datos complejos
\n\nPaso de cadenas y arreglos
\nWASM solo opera con números. Para pasar cadenas o arreglos, es necesario asignar memoria en la memoria lineal del módulo. Veamos un ejemplo en C que recibe una cadena y devuelve su longitud:
\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\nCompilamos:
\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\nCódigo JavaScript para trabajar con memoria:
\nconst createStringModule = require('./string_ops.js');\n\ncreateStringModule().then(module => {\n const { _string_length, _to_upper, heap } = module;\n \n // Asignamos memoria para la cadena\n const input = "hello world";\n const ptr = module._malloc(input.length + 1);\n \n // Copiamos la cadena a la memoria WASM\n for (let i = 0; i < input.length; i++) {\n heap[i + ptr] = input.charCodeAt(i);\n }\n heap[ptr + input.len