En los últimos meses, WebAssembly ha ganado tracción como una alternativa de alto rendimiento para ejecutar código nativo en el navegador. Si ya trabajas con Rust, ahora puedes compilar tus librerías a Wasm y consumirlas directamente desde JavaScript, sin depender de plugins o transpiladores pesados.
Ilustración por IA
En este tutorial vamos a crear una aplicación mínima que muestra un contador implementado en Rust y expuesto como módulo WebAssembly. Veremos cómo configurar el entorno, compilar el código, integrarlo en una página web y desplegarlo de forma estática.
¿Qué es WebAssembly?
WebAssembly (Wasm) es un formato binario portátil que permite ejecutar código de bajo nivel en navegadores modernos. Su diseño está pensado para ser rápido, seguro y compatible con el sandbox del navegador. Puedes consultar la documentación oficial en MDN Web Docs.
Configuración del proyecto
Comenzaremos creando una carpeta de proyecto y configurando Rust con wasm-pack, la herramienta recomendada para empaquetar crates Rust como módulos WebAssembly.
mkdir contador-wasm
cd contador-wasm
cargo init --lib
cargo install wasm-packUna vez instalado, inicializa el paquete con la configuración adecuada:
wasm-pack new --target web contadorIlustración por IA
Compilación de Rust a Wasm
Edita el archivo src/lib.rs para exponer una función que incremente un contador.
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn incrementar(valor: i32) -> i32 {
valor + 1
}
Asegúrate de añadir wasm-bindgen como dependencia en Cargo.toml:
[dependencies]
wasm-bindgen = "0.2"
Compila el crate con wasm-pack:
wasm-pack build --target webEl comando generará una carpeta pkg con los archivos .wasm, .js y los tipos TypeScript necesarios.
Integración con JavaScript
En la parte cliente, crea un archivo index.html que cargue el módulo generado y lo utilice para actualizar la UI.
<!DOCTYPE html>
<html lang='es'>
<head>
<meta charset='UTF-8'>
<title>Contador WebAssembly</title>
</head>
<body>
<h1>Contador con Rust y WebAssembly</h1>
<button id='boton'>Incrementar</button>
<span id='valor'>0</span>
<script type='module'>
import init, { incrementar } from './pkg/contador.js';
await init();
const btn = document.getElementById('boton');
const span = document.getElementById('valor');
btn.addEventListener('click', () => {
const actual = Number(span.textContent);
span.textContent = incrementar(actual);
});
</script>
</body>
</html>
El módulo se carga mediante import y la función incrementar se invoca directamente desde el código JavaScript, manteniendo una interfaz sencilla.
Foto por Chris Ried en Unsplash
Despliegue y buenas prácticas
Para servir el archivo .wasm con los encabezados correctos, utiliza un servidor estático que incluya Content-Type: application/wasm. Por ejemplo, con http-server:
npx http-server . -c-1Considera habilitar la caché de los módulos y usar integrity hashes para mayor seguridad. Además, revisa la compatibilidad con navegadores mediante la tabla de soporte de caniuse.com.
Conclusión
Hemos recorrido todo el flujo: desde la escritura de lógica en Rust, pasando por la compilación a WebAssembly, hasta su consumo en una aplicación web. Esta cadena permite aprovechar el rendimiento de Rust sin abandonar el ecosistema JavaScript, abriendo la puerta a casos de uso como videojuegos, procesamiento de imágenes o algoritmos intensivos.