¿Qué es WebAssembly?
WebAssembly (Wasm) es un formato de instrucción binaria para una máquina virtual basada en pila, diseñado como objetivo de compilación portátil para lenguajes de alto nivel. Estandarizado por el W3C en 2019 (el primer nuevo lenguaje soportado de forma nativa en navegadores desde JavaScript en 1995), WebAssembly se ejecuta a velocidad casi nativa en todos los principales navegadores web y cada vez más en entornos de servidor y embebidos.
WebAssembly no es un sustituto de JavaScript — es un complemento. JavaScript sigue siendo el lenguaje de la manipulación del DOM, las APIs web y la interacción dirigida por eventos. WebAssembly maneja tareas computacionalmente intensivas: procesamiento de imágenes, codificación de vídeo, gráficos 3D, criptografía, simulación científica y ejecución de bases de código nativas existentes (C, C++, Rust) en la web sin reescribirlas.
Los formatos de archivo WebAssembly
WebAssembly existe en dos representaciones:
1. Formato binario (.wasm)
El formato binario es lo que ejecutan los navegadores. Es compacto, rápido de analizar y no legible por humanos. Un archivo .wasm comienza con un número mágico (\0asm, hex 00 61 73 6D) seguido de un número de versión.
# Verificar un archivo .wasm
file app.wasm # WebAssembly (wasm) binary module
xxd app.wasm | head -2 # 0000: 0061 736d 0100 0000 ...
wc -c app.wasm # tamaño en bytes
2. Formato de texto (.wat)
El formato de texto WebAssembly es el equivalente legible por humanos, usando S-expressions (sintaxis entre paréntesis similar a Lisp). Se usa principalmente para depuración y aprendizaje.
;; factorial.wat — calcula n!
(module
(func $factorial (export "factorial") (param $n i32) (result i64)
(if (result i64)
(i32.le_s (local.get $n) (i32.const 1))
(then (i64.const 1))
(else
(i64.mul
(i64.extend_i32_s (local.get $n))
(call $factorial
(i32.sub (local.get $n) (i32.const 1))
)
)
)
)
)
)
Convertir entre binario y texto:
# Binario (.wasm) → Texto (.wat)
wasm2wat app.wasm -o app.wat
# Texto (.wat) → Binario (.wasm)
wat2wasm factorial.wat -o factorial.wasm
Compilar a WebAssembly
Desde C/C++ con Emscripten
Emscripten es la cadena de herramientas principal para compilar C/C++ a WebAssembly:
# Instalar Emscripten
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk && ./emsdk install latest && ./emsdk activate latest
source ./emsdk_env.sh
# Compilar un programa C a WebAssembly (genera hello.js + hello.wasm)
emcc hello.c -O3 \
-s EXPORTED_FUNCTIONS='["_add","_main"]' \
-s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' \
-o hello.js
Desde Rust con wasm-pack
Rust + wasm-pack es el camino más ergonómico hacia WebAssembly de grado de producción:
# Instalar wasm-pack
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
# Crear un nuevo proyecto Rust + Wasm
cargo new --lib mi_libreria_wasm
cd mi_libreria_wasm
// src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn saludar(nombre: &str) -> String {
format!("Hola, {}! Desde Rust/WebAssembly.", nombre)
}
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
match n {
0 => 0,
1 => 1,
_ => {
let mut a = 0u64;
let mut b = 1u64;
for _ in 2..=n {
let c = a + b;
a = b;
b = c;
}
b
}
}
}
# Compilar (genera directorio pkg/ con .wasm + bindings JS)
wasm-pack build --target web
Usar WebAssembly en el navegador
API JavaScript nativa
// Cargar e instanciar un módulo .wasm
async function cargarWasm() {
// Instanciación en streaming (la más rápida)
const { instance } = await WebAssembly.instantiateStreaming(
fetch('factorial.wasm'),
{} // objeto de importaciones (vacío para este módulo)
);
// Llamar a funciones exportadas
const resultado = instance.exports.factorial(10);
console.log(`10! = ${resultado}`); // 3628800
}
cargarWasm();
Usando un módulo Rust/wasm-pack
<script type="module">
import init, { saludar, fibonacci } from './pkg/mi_libreria_wasm.js';
async function ejecutar() {
await init(); // carga e instancia el archivo .wasm
console.log(saludar("Mundo")); // "Hola, Mundo! Desde Rust/WebAssembly."
console.log(fibonacci(40)); // 102334155 (¡rápido!)
}
ejecutar();
</script>
WebAssembly más allá del navegador
WASI (WebAssembly System Interface) — una API estandarizada para acceder a recursos del sistema operativo (archivos, red, relojes) desde WebAssembly. Permite que los módulos Wasm se ejecuten en el servidor como binarios nativos portátiles y aislados.
# Ejecutar un archivo .wasm con Wasmtime (runtime WASI)
wasmtime hola.wasm
# Ejecutar con acceso al sistema de archivos concedido
wasmtime --dir=./datos procesar.wasm
Computación en el borde (edge): Cloudflare Workers, Fastly Compute@Edge y Vercel Edge Functions ejecutan WebAssembly en el borde de la red — latencia ultrabaja con un sandbox de seguridad más robusto que los contenedores.
Sistemas de plugins: Aplicaciones como Envoy Proxy y motores de juegos usan WebAssembly como formato de plugin seguro donde el código de terceros se ejecuta en un sandbox aislado.
Aplicaciones reales de WebAssembly
| Aplicación | Qué se ejecuta en Wasm | Tecnología |
|---|---|---|
| Figma | Motor de renderizado vectorial | C++ / Emscripten |
| Google Earth | Renderizado del globo 3D | C++ / Emscripten |
| AutoCAD Web | Motor CAD | C++ / Emscripten |
| Photoshop Web | Códecs de procesamiento de imagen | C++ / Emscripten |
| Squoosh | Compresión de imagen (WebP, AVIF, etc.) | C++ / Rust |
| FFmpeg.wasm | Conversión de vídeo/audio en el navegador | C / Emscripten |
| PyScript | Intérprete Python | CPython / Emscripten |
| SQLite en el navegador | Base de datos SQLite completa | C / Emscripten |
Características de rendimiento
WebAssembly típicamente logra el 70-90% del rendimiento nativo de C++ — una mejora dramática sobre JavaScript para tareas computacionalmente intensivas:
- Rendimiento determinista: sin pausas de recolección de basura (Wasm usa memoria lineal, no un heap con GC)
- Optimización predecible: el formato binario está diseñado para compilación de un solo paso
- SIMD: el tipo de vector v128 permite ejecución paralela de datos
- Hilos: la API
SharedArrayBuffer+Atomicspermite WebAssembly multi-hilo
¿Qué lenguajes pueden compilarse a WebAssembly?
Muchos lenguajes pueden compilarse a WebAssembly: C y C++ mediante Emscripten (la cadena de herramientas más madura); Rust mediante wasm-pack/wasm-bindgen (excelente ergonomía y sin sobrecarga de runtime); Go (experimental, pero incluye un runtime Go completo); AssemblyScript (lenguaje similar a TypeScript diseñado específicamente para Wasm); Kotlin/Native, Swift y Zig (con niveles de soporte variables). Python se ejecuta en WebAssembly a través de Pyodide (CPython compilado con Emscripten) y PyScript.
Conversiones relacionadas
Conversiones frecuentes del catálogo: