para esta charla en mi página de GitHub. Entonces, el elefante en la habitación, ¿qué es
WebAssembly y cómo es útil? Bueno,
WebAssembly, o
WASM, es básicamente una abstracción de bajo nivel para la CPU en la que se ejecuta tu código. Es un bytecode rápido y compacto en el sentido de que es un formato binario portátil para una máquina virtual que modela las operaciones de carga y almacenamiento de números en la memoria lineal. Está diseñado para lograr una velocidad cercana a la nativa y también está optimizado para un inicio rápido y una huella de memoria pequeña. Fue creado por los proveedores de navegadores para portar código C++ a la web sin degradación del rendimiento y ahora es un objetivo de compilación portátil para muchos lenguajes, incluidos
Rust, Go y muchos otros. Eso significa que puedes compilar tu código a
WASM una vez y luego ejecutar el mismo artefacto compilado en diferentes plataformas. Por ejemplo,
Node.js admite
WebAssembly desde la versión 8 y ahora puedes importar un módulo
WASM exactamente como importarías un paquete estándar de
npm. Y ¿por qué es útil un único objetivo de compilación portátil? Considera
Node.js, un popular complemento NAPI que compila estilos SAS a
CSS. Para admitir múltiples configuraciones del sistema, arquitecturas e incluso versiones de
Node.js, esta biblioteca debe compilarse por separado para cada una de estas configuraciones. Esto significa 35 objetivos de compilación diferentes y hace que cada nueva implementación sea una tarea que consume tiempo y recursos. Aquellos de ustedes que usan
Prisma probablemente sepan que estamos en una situación similar con el
CLI de
TypeScript y una biblioteca que descarga algunos binarios compilados de
Rust bajo demanda. Esto es lo que nos hizo considerar
WebAssembly y adoptarlo tanto como para simplificar nuestro proceso de implementación. Y si alguna vez has intentado escribir complementos nativos de
Node.js, probablemente sepas que no es un proceso sencillo. A veces, no jib falla con mensajes de error crípticos y, francamente, las herramientas necesarias para construir e importar módulos de C++ no son tan amigables para los humanos como lo que los desarrolladores de
Node.js están acostumbrados a utilizar. Entonces, esta es quizás una de las principales razones por las que
Rust es consistentemente votado como el mejor lenguaje para
WebAssembly. Entonces, veamos cómo podemos crear los módulos de
TypeScript a partir de él. Y para aquellos de ustedes que son nuevos en
Rust, definamos algunos conceptos básicos, ¿de acuerdo? Entonces, cualquier cosa que uses un paquete de json para, lo colocarías en un archivo cargo.toml en un proyecto de
Rust. Lo que normalmente llamas paquetes de
npm son cajas en
Rust y operas con ellas a través del comando cargo
CLI. Por ejemplo, para compilar código
Rust, usarías el comando cargo build y especificarías el objetivo de compilación. En nuestro caso, es
Wasm 32 desconocido, desconocido. Utiliza un espacio de direccionamiento de 32 bits y no está vinculado a ningún proveedor de sistema operativo o arquitectura de CPU en particular. Si queremos mover más que solo datos numéricos a través del puente de
WebAssembly, necesitaremos una herramienta de enlace. Es tanto un
CLI como una biblioteca de
Rust. Cuando lo instalas, debes especificar una versión particular, porque aún no sigue la versión semántica. Esto significa que la versión que especificas en tu archivo cargo.toml debe coincidir con la versión de
Wasm que tienes instalada en tu máquina. Además, para admitir
WebAssembly, debes marcar tu tipo de caja como c.lib. Esto le indicará a
Rust que compile tu código como una biblioteca dinámica que puede ser cargada por un runtime compatible con C, como
Node.js. Entonces, compilar
Rust a
WebAssembly es un proceso de dos pasos. Primero, debes ejecutar cargo.build para crear un artefacto de
WebAssembly compilado, que tendrá la extensión .
wasm, y luego agregarás wasm.bindgen para generar los enlaces de
Node.js y
TypeScript que utilizarás para importar el módulo
wasm compilado. Por supuesto, si wasm.bindgen admitiera todas las estructuras de datos comúnmente utilizadas de
Rust y las convenciones de
TypeScript, esta charla ya habría terminado, y claramente ese no es el caso. Entonces veamos cómo podemos solucionar esto.