spinny:~/writing $ less webassembly-wasm-complete-guide.md
12WebAssembly (WASM) comenzo como una forma de ejecutar C++ en el navegador. En 2026, se ejecuta en todas partes - navegadores, servidores, redes edge, dispositivos embebidos - y alimenta algunas de las aplicaciones mas exigentes de la web. El motor de renderizado de Figma, Adobe Photoshop en la web, el procesamiento de video de Google Meet y la plataforma de computacion edge de Cloudflare funcionan todos sobre WebAssembly.34Chrome Platform Status situa WASM en aproximadamente el 5,5% de todas las cargas de pagina en Chrome a principios de 2026, frente al 4,5% del ano anterior. Con WASM 3.0 convertido en estandar del W3C y WASI madurando hacia la version 1.0, el ecosistema ha alcanzado un punto de inflexion.56Esta guia cubre todo lo que necesitas saber para empezar a desarrollar con WebAssembly.78## Que es WebAssembly?910WebAssembly es un formato de instrucciones binarias disenado como objetivo de compilacion. Escribes codigo en un lenguaje de alto nivel (Rust, C, C++, Go, Kotlin), lo compilas a `.wasm` y lo ejecutas en cualquier entorno que tenga un runtime WASM - navegadores, Node.js, Cloudflare Workers, Wasmtime o Wasmer.1112```mermaid13graph LR14 Rust[Rust / C / C++] --> Compiler[Compiler]15 Compiler --> WASM[.wasm Binary]16 WASM --> Browser[Browser V8/SpiderMonkey]17 WASM --> Server[Server Wasmtime]18 WASM --> Edge[Edge Cloudflare Workers]19 WASM --> Embedded[Embedded WAMR]20```2122### Como funciona2324WASM es una **maquina virtual basada en pila**. Las funciones apilan y desapilan valores en una pila de operandos. El runtime host (V8 en Chrome, SpiderMonkey en Firefox) compila JIT el bytecode WASM a codigo maquina nativo, por lo que el rendimiento es casi nativo.2526Caracteristicas clave:2728- **Ejecucion en sandbox**: los modulos WASM solo pueden acceder a los recursos que el host concede explicitamente. Sin acceso al sistema de archivos, a la red ni al sistema operativo a menos que se permita. Esto es fundamentalmente diferente del codigo nativo.29- **Memoria lineal**: un unico `ArrayBuffer` contiguo compartido entre WASM y el host. Los datos complejos (cadenas, structs) se pasan escribiendo en memoria y compartiendo un puntero.30- **Tipos limitados**: WASM soporta nativamente solo cuatro tipos: `i32`, `i64`, `f32`, `f64`. Todo lo demas (cadenas, arrays, objetos) requiere codificacion a traves de la memoria lineal o el Component Model.31- **Portable**: el mismo binario `.wasm` se ejecuta en cualquier plataforma con un runtime WASM, sin recompilacion.3233### WASM vs JavaScript3435WASM no reemplaza a JavaScript. Lo complementa.3637| Aspecto | JavaScript | WebAssembly |38|---------|-----------|-------------|39| **Parsing** | Parsing + compilacion en tiempo de ejecucion | Binario pre-compilado, solo decodificacion |40| **Velocidad de ejecucion** | Optimizado JIT, variable | Casi nativo, constante |41| **Arranque** | Rapido para scripts pequenos | Decodificacion rapida, predecible |42| **Acceso al DOM** | Directo | Indirecto (a traves de glue JS) |43| **Ideal para** | UI, manipulacion del DOM, gestion de eventos | Computacion intensiva en CPU |44| **Garbage collection** | Integrado | WasmGC (nuevo), o manual |4546Usa JavaScript para la interfaz de usuario y el trabajo con el DOM. Usa WASM para el calculo pesado: procesamiento de imagenes, codificacion de video, simulaciones fisicas, criptografia, parsing de datos.4748## WASM 3.0: las novedades4950WebAssembly 3.0 se convirtio en estandar del W3C en septiembre de 2025, estandarizando nueve funcionalidades que llevaban anos en desarrollo.5152| Funcionalidad | Que permite |53|---------------|------------|54| **WasmGC** | Garbage collection nativa en WASM. Los lenguajes gestionados (Java, Kotlin, Dart) pueden compilar a WASM sin incluir su propio runtime GC. Soportado en Chrome 119+, Firefox 120+, Safari 18.2+. |55| **Exception Handling** | `try`/`catch` nativos en WASM. Antes, las excepciones requerian costosos viajes de ida y vuelta a JavaScript. |56| **Tail Calls** | Permite recursion eficiente sin stack overflow. Fundamental para los lenguajes funcionales. |57| **Relaxed SIMD** | Instrucciones vectoriales de 128 bits para el procesamiento paralelo de datos. Permite optimizaciones especificas del hardware. |58| **Memory64** | Supera el limite de 4GB de memoria lineal. Necesario para el procesamiento de datos a gran escala. |59| **Multi-memory** | Multiples regiones de memoria independientes en un solo modulo. |6061La mas impactante es **WasmGC**. Antes de ella, compilar Java o Kotlin a WASM significaba incluir un garbage collector completo como parte del binario, inflando el tamano de los archivos. Ahora el GC del navegador gestiona la memoria para los modulos WASM, igual que lo hace para JavaScript.6263## WASI: WebAssembly mas alla del navegador6465WASM en el navegador es potente, pero **WASI (WebAssembly System Interface)** es lo que convierte a WASM en un runtime universal. WASI proporciona interfaces estandarizadas para recursos del sistema - archivos, red, relojes, numeros aleatorios - permitiendo que los modulos WASM funcionen fuera del navegador.6667```mermaid68graph TD69 subgraph "Browser"70 B[WASM Module] --> Web[Web APIs\nDOM, Fetch, Canvas]71 end7273 subgraph "Server / Edge / Embedded"74 S[WASM Module] --> WASI[WASI Interfaces]75 WASI --> FS[wasi:filesystem]76 WASI --> Net[wasi:sockets]77 WASI --> HTTP[wasi:http]78 WASI --> Clock[wasi:clocks]79 WASI --> Rand[wasi:random]80 end81```8283WASI Preview 2 (la version estable actual) define estas interfaces:8485- `wasi:filesystem` - operaciones con archivos mediante handles de capacidad (no los descriptores de archivo tradicionales)86- `wasi:sockets` - red TCP/UDP87- `wasi:http` - gestion de peticiones/respuestas HTTP88- `wasi:clocks` - reloj de sistema, reloj monotonico89- `wasi:random` - aleatoriedad criptografica90- `wasi:cli` - argumentos de linea de comandos, variables de entorno, stdio9192El principio clave es la **seguridad basada en capacidades**: un modulo WASM no puede acceder al sistema de archivos a menos que el host conceda explicitamente un handle a un directorio especifico. Esto hace que WASI sea fundamentalmente mas seguro que ejecutar ejecutables nativos.9394### El camino hacia WASI 1.09596WASI 0.3.0 (que anade primitivas async/concurrencia) se espera en 2026, con WASI 1.0 a continuacion. La adicion principal es el async integrado en el lenguaje con I/O streaming de copia cero.9798## El Component Model99100Los modulos WASM basicos solo pueden intercambiar numeros. El **Component Model** resuelve esta limitacion anadiendo un sistema de tipos rico y una capa de composabilidad sobre WASM.101102### WIT (WebAssembly Interface Types)103104WIT es un lenguaje de definicion de interfaces que permite a los componentes declarar sus importaciones y exportaciones con tipos ricos - cadenas, registros, listas, variantes, enumeraciones - no solo `i32` y `f64`.105106```wit107// calculator.wit108package myorg:calculator@1.0.0;109110interface operations {111 record calculation {112 expression: string,113 result: f64,114 timestamp: u64,115 }116117 add: func(a: f64, b: f64) -> f64;118 multiply: func(a: f64, b: f64) -> f64;119 history: func() -> list<calculation>;120}121122world calculator {123 export operations;124}125```126127Las toolchains como `wit-bindgen` generan bindings especificos del lenguaje a partir de archivos WIT. Un componente Rust y un componente Python pueden intercambiar cadenas, registros y listas a traves de contratos WIT sin que ninguna de las partes conozca el lenguaje de implementacion de la otra.128129## Construir tu primer modulo WASM con Rust130131Rust tiene las herramientas WASM mas maduras. Construyamos un ejemplo practico: un modulo de procesamiento de imagenes que se ejecuta en el navegador.132133### Configuracion134135```bash136# Install the WASM target for Rust137rustup target add wasm32-unknown-unknown138139# Install wasm-pack (builds Rust to WASM + generates JS bindings)140cargo install wasm-pack141142# Create a new library project143cargo new --lib image-processor144cd image-processor145```146147### Configurar Cargo.toml148149```toml150[package]151name = "image-processor"152version = "0.1.0"153edition = "2021"154155[lib]156crate-type = ["cdylib"]157158[dependencies]159wasm-bindgen = "0.2"160```161162### Escribir el codigo Rust163164```rust165// src/lib.rs166use wasm_bindgen::prelude::*;167168/// Convert an image buffer to grayscale.169/// Input: RGBA pixel data as a flat u8 array (4 bytes per pixel).170/// Output: Modified in place for zero-copy performance.171#[wasm_bindgen]172pub fn grayscale(pixels: &mut [u8]) {173 for chunk in pixels.chunks_exact_mut(4) {174 let r = chunk[0] as f32;175 let g = chunk[1] as f32;176 let b = chunk[2] as f32;177 // ITU-R BT.709 luminance coefficients178 let gray = (0.2126 * r + 0.7152 * g + 0.0722 * b) as u8;179 chunk[0] = gray;180 chunk[1] = gray;181 chunk[2] = gray;182 // chunk[3] is alpha, leave unchanged183 }184}185186/// Adjust brightness of an image.187/// factor > 1.0 brightens, < 1.0 darkens.188#[wasm_bindgen]189pub fn adjust_brightness(pixels: &mut [u8], factor: f32) {190 for chunk in pixels.chunks_exact_mut(4) {191 chunk[0] = ((chunk[0] as f32 * factor).min(255.0)) as u8;192 chunk[1] = ((chunk[1] as f32 * factor).min(255.0)) as u8;193 chunk[2] = ((chunk[2] as f32 * factor).min(255.0)) as u8;194 }195}196197/// Invert all colors in the image.198#[wasm_bindgen]199pub fn invert(pixels: &mut [u8]) {200 for chunk in pixels.chunks_exact_mut(4) {201 chunk[0] = 255 - chunk[0];202 chunk[1] = 255 - chunk[1];203 chunk[2] = 255 - chunk[2];204 }205}206207/// Calculate the average brightness of an image (0-255).208#[wasm_bindgen]209pub fn average_brightness(pixels: &[u8]) -> f32 {210 let mut total: f64 = 0.0;211 let pixel_count = pixels.len() / 4;212 for chunk in pixels.chunks_exact(4) {213 let luminance = 0.2126 * chunk[0] as f64214 + 0.7152 * chunk[1] as f64215 + 0.0722 * chunk[2] as f64;216 total += luminance;217 }218 (total / pixel_count as f64) as f32219}220```221222### Build223224```bash225wasm-pack build --target web226```227228Esto produce un directorio `pkg/` con:229- `image_processor_bg.wasm` - el binario WASM compilado230- `image_processor.js` - codigo glue JavaScript con definiciones TypeScript231- `package.json` - listo para publicar en npm232233### Uso en JavaScript234235```html236<!DOCTYPE html>237<html>238<head><title>WASM Image Processor</title></head>239<body>240 <canvas id="canvas" width="800" height="600"></canvas>241 <button onclick="applyGrayscale()">Grayscale</button>242 <button onclick="applyBrightness()">Brighten</button>243 <button onclick="applyInvert()">Invert</button>244245 <script type="module">246 import init, { grayscale, adjust_brightness, invert } from "./pkg/image_processor.js";247248 let ctx;249 let imageData;250251 async function setup() {252 await init();253 const canvas = document.getElementById("canvas");254 ctx = canvas.getContext("2d");255256 // Load an image onto the canvas257 const img = new Image();258 img.onload = () => {259 ctx.drawImage(img, 0, 0);260 imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);261 };262 img.src = "photo.jpg";263 }264265 window.applyGrayscale = () => {266 grayscale(imageData.data);267 ctx.putImageData(imageData, 0, 0);268 };269270 window.applyBrightness = () => {271 adjust_brightness(imageData.data, 1.3);272 ctx.putImageData(imageData, 0, 0);273 };274275 window.applyInvert = () => {276 invert(imageData.data);277 ctx.putImageData(imageData, 0, 0);278 };279280 setup();281 </script>282</body>283</html>284```285286El punto clave: `imageData.data` es un `Uint8ClampedArray` respaldado por un `ArrayBuffer`. Cuando se pasa a WASM, comparte la misma memoria - sin copias. La funcion Rust modifica los pixeles directamente, y el lado JavaScript ve los cambios inmediatamente.287288## Nivel inferior: instanciacion manual de WASM289290Si no quieres usar `wasm-bindgen`, puedes instanciar los modulos WASM directamente:291292```javascript293const response = await fetch("calculator.wasm");294const { instance } = await WebAssembly.instantiateStreaming(response, {295 env: {296 // Functions the WASM module can call297 log_result: (value) => console.log("Result:", value),298 },299});300301// Call exported functions302const { add, multiply } = instance.exports;303console.log(add(5, 3)); // 8304console.log(multiply(4, 7)); // 28305```306307Esto es util cuando quieres un overhead minimo y no necesitas interoperabilidad avanzada entre tipos.308309## Rendimiento: WASM vs JavaScript310311Los benchmarks reales muestran aceleraciones significativas para tareas intensivas en CPU:312313| Tarea | JavaScript | WASM | Aceleracion |314|-------|-----------|------|-------------|315| Procesamiento de imagen 4K | 180ms | 8ms (con SIMD) | 22x |316| Redimensionamiento de imagen (4K) | 250ms | 45ms | 5,5x |317| Simulacion fisica (10K entidades) | Frames perdidos | 60fps fluidos | ~10x |318| Parsing JSON (carga grande) | 12ms | 3ms | 4x |319| Hashing criptografico | 45ms | 6ms | 7,5x |320321WASM funciona a aproximadamente el 95% de la velocidad del codigo nativo. Las mayores ganancias provienen de:322- Rendimiento predecible (sin warmup JIT, sin pausas del GC)323- Instrucciones SIMD para el procesamiento paralelo de datos324- Acceso directo a memoria sin interferencia del garbage collector325326Donde WASM NO es mas rapido: manipulacion del DOM, calculos pequenos, tareas limitadas por I/O. JavaScript ya esta optimizado para estos casos.327328## Casos de uso en produccion329330### Figma: renderizado vectorial en tiempo real331332El motor de renderizado principal de Figma es C++ compilado a WASM. Cada forma, gradiente y efecto se calcula en WASM y se dibuja en un elemento Canvas. Esto permite a Figma manejar disenos complejos con miles de capas a 60fps en el navegador - un rendimiento imposible en JavaScript puro.333334### Adobe Photoshop en la web335336Adobe porto filtros y herramientas clave de Photoshop a WASM usando Rust. Sus benchmarks muestran procesamiento de imagenes 4K en 22ms con WASM SIMD frente a 180ms en JavaScript - una mejora de 8 veces que hace posibles las previsualizaciones de filtros en tiempo real.337338### Cloudflare Workers339340Cloudflare ejecuta modulos WASM en isolates V8 en mas de 330 ubicaciones edge. Los cold starts son de 1 a 5ms (comparados con 100 a 500ms del serverless basado en contenedores). En febrero de 2026, desplegaron la inferencia de Llama-3-8b en su red edge usando WASM.341342### Google Meet343344El desenfoque de fondo y los fondos virtuales en Google Meet utilizan WASM con SIMD para el procesamiento de video en tiempo real. El modulo WASM procesa cada frame de video lo suficientemente rapido para mantener un video fluido a 30fps.345346## Soporte de navegadores (2026)347348| Funcionalidad | Chrome | Firefox | Safari | Edge |349|---------------|--------|---------|--------|------|350| Core WASM | Completo | Completo | Completo | Completo |351| Threads | Si | Si | Si | Si |352| SIMD (128 bits) | Si | Si | Si | Si |353| WasmGC | 119+ | 120+ | 18.2+ | Si |354| Exception Handling | Si | Si | Si | Si |355| Memory64 | Si | Si | Parcial | Si |356357Todos los navegadores principales soportan completamente WASM. Las funcionalidades mas recientes (WasmGC, Exception Handling) han alcanzado una amplia disponibilidad.358359## Referencia de herramientas360361| Herramienta | Proposito | Instalacion |362|-------------|-----------|-------------|363| **wasm-pack** | Compilar Rust a WASM, generar paquetes npm | `cargo install wasm-pack` |364| **wasm-bindgen** | Bindings de interoperabilidad Rust/JS (usado por wasm-pack) | Dependencia en Cargo.toml |365| **wasm-opt** | Optimizacion del tamano del binario (reduccion del 50%+) | Parte de Binaryen: `brew install binaryen` |366| **wit-bindgen** | Generar bindings desde archivos WIT | `cargo install wit-bindgen-cli` |367| **Wasmtime** | Runtime WASM del lado del servidor (implementacion de referencia WASI) | `brew install wasmtime` |368| **Wasmer** | Runtime WASM alternativo con soporte WASI | `curl https://get.wasmer.io -sSfL \| sh` |369| **wasm-feature-detect** | Deteccion de funcionalidades del navegador en tiempo de ejecucion | `npm install wasm-feature-detect` |370371### Optimizar el tamano del binario372373Los binarios WASM pueden ser grandes. Asi es como reducirlos:374375```toml376# Cargo.toml377[profile.release]378opt-level = "z" # Optimize for size379lto = true # Link-time optimization380codegen-units = 1 # Better optimization, slower compile381strip = true # Strip debug symbols382```383384```bash385# Build in release mode386wasm-pack build --release --target web387388# Further optimize with wasm-opt389wasm-opt -Oz pkg/image_processor_bg.wasm -o pkg/image_processor_bg.wasm390```391392Un modulo WASM tipico en Rust pasa de 500KB a menos de 50KB con estas optimizaciones.393394## Hoja de ruta para empezar395396```mermaid397flowchart TD398 A[Week 1: Basics] --> B[Week 2: Real Project]399 B --> C[Week 3: WASI and Server-side]400 C --> D[Month 2+: Production]401402 A --> A1[Install Rust + wasm-pack]403 A --> A2[Build hello-world WASM module]404 A --> A3[Call WASM functions from JavaScript]405406 B --> B1[Build image processor or game physics]407 B --> B2[Use wasm-bindgen for rich types]408 B --> B3[Benchmark against pure JS]409410 C --> C1[Run WASM with Wasmtime]411 C --> C2[Explore WASI interfaces]412 C --> C3[Try Component Model with WIT]413414 D --> D1[Optimize binary size]415 D --> D2[Use SIMD for parallelism]416 D --> D3[Deploy to Cloudflare Workers or browser]417```418419## Conclusion420421WebAssembly ya no es experimental. Es una tecnologia de produccion utilizada por algunas de las aplicaciones mas exigentes de la web. Rendimiento casi nativo, seguridad en sandbox y portabilidad universal - ningun otro objetivo de compilacion te ofrece las tres cosas.422423No necesitas reescribir toda tu aplicacion en WASM. Empieza con una sola funcion intensiva en CPU - un filtro de imagen, un parser de datos, un calculo fisico - compilala a WASM y llamala desde JavaScript. Mide la diferencia. Luego decide donde mas puede ayudar WASM.424425Las herramientas son maduras, el soporte de navegadores es universal y el ecosistema esta creciendo. Si escribes en Rust, ya estas a un comando de distancia del navegador.426427> **Checklist para empezar:**428>429> - [x] Rust y wasm-pack instalados430> - [x] Primer modulo WASM compilado y funcionando en el navegador431> - [x] Interoperabilidad con JavaScript funcionando (llamar a WASM desde JS)432> - [x] Build de release con optimizaciones de tamano aplicadas433> - [x] Rendimiento comparado con el equivalente en JavaScript puro434> - [x] WASI explorado con Wasmtime para casos de uso del lado del servidor435
:WebAssembly para desarrolladores web: de cero a produccionlines 1-435 (END) — press q to close