WebAssembly (WASM) comecou como uma forma de executar C++ no navegador. Em 2026, ele roda em todo lugar - navegadores, servidores, redes edge, dispositivos embarcados - e alimenta algumas das aplicacoes mais exigentes da web. O motor de renderizacao do Figma, o Adobe Photoshop na web, o processamento de video do Google Meet e a plataforma de computacao edge da Cloudflare funcionam todos sobre WebAssembly.
O Chrome Platform Status situa o WASM em aproximadamente 5,5% de todos os carregamentos de pagina no Chrome no inicio de 2026, acima dos 4,5% do ano anterior. Com o WASM 3.0 tornado padrao W3C e o WASI amadurecendo rumo a versao 1.0, o ecossistema atingiu um ponto de virada.
Este guia cobre tudo o que voce precisa saber para comecar a desenvolver com WebAssembly.
O que e WebAssembly?
WebAssembly e um formato de instrucoes binarias projetado como alvo de compilacao. Voce escreve codigo em uma linguagem de alto nivel (Rust, C, C++, Go, Kotlin), compila para .wasm e executa em qualquer ambiente que tenha um runtime WASM - navegadores, Node.js, Cloudflare Workers, Wasmtime ou Wasmer.
Como funciona
WASM e uma maquina virtual baseada em pilha. As funcoes empilham e desempilham valores em uma pilha de operandos. O runtime host (V8 no Chrome, SpiderMonkey no Firefox) compila JIT o bytecode WASM em codigo de maquina nativo, por isso o desempenho e quase nativo.
Caracteristicas principais:
- Execucao em sandbox: os modulos WASM so podem acessar recursos que o host concede explicitamente. Sem acesso ao sistema de arquivos, a rede ou ao sistema operacional, a menos que seja permitido. Isso e fundamentalmente diferente do codigo nativo.
- Memoria linear: um unico
ArrayBuffercontiguo compartilhado entre WASM e o host. Dados complexos (strings, structs) sao passados escrevendo na memoria e compartilhando um ponteiro. - Tipos limitados: WASM suporta nativamente apenas quatro tipos:
i32,i64,f32,f64. Todo o resto (strings, arrays, objetos) requer codificacao atraves da memoria linear ou do Component Model. - Portavel: o mesmo binario
.wasmroda em qualquer plataforma com um runtime WASM, sem recompilacao.
WASM vs JavaScript
WASM nao substitui JavaScript. Ele o complementa.
| Aspecto | JavaScript | WebAssembly |
|---|---|---|
| Parsing | Parsing + compilacao em tempo de execucao | Binario pre-compilado, apenas decodificacao |
| Velocidade de execucao | Otimizado JIT, variavel | Quase nativo, constante |
| Inicializacao | Rapida para scripts pequenos | Decodificacao rapida, previsivel |
| Acesso ao DOM | Direto | Indireto (atraves de glue JS) |
| Ideal para | UI, manipulacao do DOM, tratamento de eventos | Computacao intensiva em CPU |
| Garbage collection | Integrado | WasmGC (novo), ou manual |
Use JavaScript para interface de usuario e trabalho com o DOM. Use WASM para computacao pesada: processamento de imagens, codificacao de video, simulacoes fisicas, criptografia, parsing de dados.
WASM 3.0: as novidades
WebAssembly 3.0 tornou-se padrao W3C em setembro de 2025, padronizando nove funcionalidades que estavam em desenvolvimento ha anos.
| Funcionalidade | O que permite |
|---|---|
| WasmGC | Garbage collection nativa no WASM. Linguagens gerenciadas (Java, Kotlin, Dart) podem compilar para WASM sem incluir seu proprio runtime GC. Suportado no Chrome 119+, Firefox 120+, Safari 18.2+. |
| Exception Handling | try/catch nativos no WASM. Antes, as excecoes exigiam ida e volta custosas ao JavaScript. |
| Tail Calls | Permite recursao eficiente sem stack overflow. Fundamental para linguagens funcionais. |
| Relaxed SIMD | Instrucoes vetoriais de 128 bits para processamento paralelo de dados. Permite otimizacoes especificas de hardware. |
| Memory64 | Ultrapassa o limite de 4GB de memoria linear. Necessario para processamento de dados em larga escala. |
| Multi-memory | Multiplas regioes de memoria independentes em um unico modulo. |
A mais impactante e o WasmGC. Antes dele, compilar Java ou Kotlin para WASM significava incluir um garbage collector completo como parte do binario, inflando o tamanho dos arquivos. Agora o GC do navegador gerencia a memoria para os modulos WASM, assim como faz para JavaScript.
WASI: WebAssembly alem do navegador
WASM no navegador e poderoso, mas o WASI (WebAssembly System Interface) e o que torna o WASM um runtime universal. O WASI fornece interfaces padronizadas para recursos do sistema - arquivos, rede, relogios, numeros aleatorios - permitindo que modulos WASM funcionem fora do navegador.
O WASI Preview 2 (a versao estavel atual) define estas interfaces:
wasi:filesystem- operacoes com arquivos via handles de capacidade (nao os descritores de arquivo tradicionais)wasi:sockets- rede TCP/UDPwasi:http- tratamento de requisicoes/respostas HTTPwasi:clocks- relogio do sistema, relogio monotonicowasi:random- aleatoriedade criptograficawasi:cli- argumentos de linha de comando, variaveis de ambiente, stdio
O principio chave e a seguranca baseada em capacidades: um modulo WASM nao pode acessar o sistema de arquivos a menos que o host conceda explicitamente um handle para um diretorio especifico. Isso torna o WASI fundamentalmente mais seguro do que executar executaveis nativos.
O caminho para o WASI 1.0
O WASI 0.3.0 (adicionando primitivas async/concorrencia) e esperado em 2026, com o WASI 1.0 a seguir. A principal adicao e o async integrado a linguagem com I/O streaming de copia zero.
O Component Model
Os modulos WASM basicos so podem trocar numeros. O Component Model resolve essa limitacao adicionando um sistema de tipos rico e uma camada de composabilidade sobre o WASM.
WIT (WebAssembly Interface Types)
WIT e uma linguagem de definicao de interfaces que permite aos componentes declarar suas importacoes e exportacoes com tipos ricos - strings, registros, listas, variantes, enumeracoes - nao apenas i32 e f64.
// calculator.wit package myorg:calculator@1.0.0; interface operations { record calculation { expression: string, result: f64, timestamp: u64, } add: func(a: f64, b: f64) -> f64; multiply: func(a: f64, b: f64) -> f64; history: func() -> list<calculation>; } world calculator { export operations; }
As toolchains como wit-bindgen geram bindings especificos da linguagem a partir de arquivos WIT. Um componente Rust e um componente Python podem trocar strings, registros e listas atraves de contratos WIT sem que nenhuma das partes conheca a linguagem de implementacao da outra.
Construindo seu primeiro modulo WASM com Rust
Rust tem as ferramentas WASM mais maduras. Vamos construir um exemplo pratico: um modulo de processamento de imagens que roda no navegador.
Configuracao
# Install the WASM target for Rust rustup target add wasm32-unknown-unknown # Install wasm-pack (builds Rust to WASM + generates JS bindings) cargo install wasm-pack # Create a new library project cargo new --lib image-processor cd image-processor
Configurar o Cargo.toml
[package] name = "image-processor" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] wasm-bindgen = "0.2"
Escrever o codigo Rust
// src/lib.rs use wasm_bindgen::prelude::*; /// Convert an image buffer to grayscale. /// Input: RGBA pixel data as a flat u8 array (4 bytes per pixel). /// Output: Modified in place for zero-copy performance. #[wasm_bindgen] pub fn grayscale(pixels: &mut [u8]) { for chunk in pixels.chunks_exact_mut(4) { let r = chunk[0] as f32; let g = chunk[1] as f32; let b = chunk[2] as f32; // ITU-R BT.709 luminance coefficients let gray = (0.2126 * r + 0.7152 * g + 0.0722 * b) as u8; chunk[0] = gray; chunk[1] = gray; chunk[2] = gray; // chunk[3] is alpha, leave unchanged } } /// Adjust brightness of an image. /// factor > 1.0 brightens, < 1.0 darkens. #[wasm_bindgen] pub fn adjust_brightness(pixels: &mut [u8], factor: f32) { for chunk in pixels.chunks_exact_mut(4) { chunk[0] = ((chunk[0] as f32 * factor).min(255.0)) as u8; chunk[1] = ((chunk[1] as f32 * factor).min(255.0)) as u8; chunk[2] = ((chunk[2] as f32 * factor).min(255.0)) as u8; } } /// Invert all colors in the image. #[wasm_bindgen] pub fn invert(pixels: &mut [u8]) { for chunk in pixels.chunks_exact_mut(4) { chunk[0] = 255 - chunk[0]; chunk[1] = 255 - chunk[1]; chunk[2] = 255 - chunk[2]; } } /// Calculate the average brightness of an image (0-255). #[wasm_bindgen] pub fn average_brightness(pixels: &[u8]) -> f32 { let mut total: f64 = 0.0; let pixel_count = pixels.len() / 4; for chunk in pixels.chunks_exact(4) { let luminance = 0.2126 * chunk[0] as f64 + 0.7152 * chunk[1] as f64 + 0.0722 * chunk[2] as f64; total += luminance; } (total / pixel_count as f64) as f32 }
Build
wasm-pack build --target web
Isso produz um diretorio pkg/ com:
image_processor_bg.wasm- o binario WASM compiladoimage_processor.js- codigo glue JavaScript com definicoes TypeScriptpackage.json- pronto para publicar no npm
Uso em JavaScript
<!DOCTYPE html> <html> <head><title>WASM Image Processor</title></head> <body> <canvas id="canvas" width="800" height="600"></canvas> <button onclick="applyGrayscale()">Grayscale</button> <button onclick="applyBrightness()">Brighten</button> <button onclick="applyInvert()">Invert</button> <script type="module"> import init, { grayscale, adjust_brightness, invert } from "./pkg/image_processor.js"; let ctx; let imageData; async function setup() { await init(); const canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); // Load an image onto the canvas const img = new Image(); img.onload = () => { ctx.drawImage(img, 0, 0); imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); }; img.src = "photo.jpg"; } window.applyGrayscale = () => { grayscale(imageData.data); ctx.putImageData(imageData, 0, 0); }; window.applyBrightness = () => { adjust_brightness(imageData.data, 1.3); ctx.putImageData(imageData, 0, 0); }; window.applyInvert = () => { invert(imageData.data); ctx.putImageData(imageData, 0, 0); }; setup(); </script> </body> </html>
O ponto chave: imageData.data e um Uint8ClampedArray apoiado por um ArrayBuffer. Quando passado para o WASM, compartilha a mesma memoria - sem copias. A funcao Rust modifica os pixels diretamente, e o lado JavaScript ve as mudancas imediatamente.
Nivel mais baixo: instanciacao manual do WASM
Se voce nao quiser usar o wasm-bindgen, pode instanciar modulos WASM diretamente:
const response = await fetch("calculator.wasm"); const { instance } = await WebAssembly.instantiateStreaming(response, { env: { // Functions the WASM module can call log_result: (value) => console.log("Result:", value), }, }); // Call exported functions const { add, multiply } = instance.exports; console.log(add(5, 3)); // 8 console.log(multiply(4, 7)); // 28
Isso e util quando voce quer overhead minimo e nao precisa de interoperabilidade avancada entre tipos.
Desempenho: WASM vs JavaScript
Benchmarks reais mostram aceleracoes significativas para tarefas intensivas em CPU:
| Tarefa | JavaScript | WASM | Aceleracao |
|---|---|---|---|
| Processamento de imagem 4K | 180ms | 8ms (com SIMD) | 22x |
| Redimensionamento de imagem (4K) | 250ms | 45ms | 5,5x |
| Simulacao fisica (10K entidades) | Frames perdidos | 60fps fluidos | ~10x |
| Parsing JSON (carga grande) | 12ms | 3ms | 4x |
| Hashing criptografico | 45ms | 6ms | 7,5x |
WASM roda a aproximadamente 95% da velocidade do codigo nativo. Os maiores ganhos vem de:
- Desempenho previsivel (sem warmup JIT, sem pausas do GC)
- Instrucoes SIMD para processamento paralelo de dados
- Acesso direto a memoria sem interferencia do garbage collector
Onde o WASM NAO e mais rapido: manipulacao do DOM, calculos pequenos, tarefas limitadas por I/O. JavaScript ja esta otimizado para esses casos.
Casos de uso em producao
Figma: renderizacao vetorial em tempo real
O motor de renderizacao principal do Figma e C++ compilado para WASM. Cada forma, gradiente e efeito e calculado em WASM e desenhado em um elemento Canvas. Isso permite ao Figma lidar com designs complexos com milhares de camadas a 60fps no navegador - desempenho impossivel em JavaScript puro.
Adobe Photoshop na web
A Adobe portou filtros e ferramentas chave do Photoshop para WASM usando Rust. Seus benchmarks mostram processamento de imagens 4K em 22ms com WASM SIMD contra 180ms em JavaScript - uma melhoria de 8 vezes que torna possiveis as previsualizacoes de filtros em tempo real.
Cloudflare Workers
A Cloudflare executa modulos WASM em isolates V8 em mais de 330 localizacoes edge. Os cold starts sao de 1 a 5ms (comparados com 100 a 500ms do serverless baseado em conteineres). Em fevereiro de 2026, implantaram a inferencia do Llama-3-8b em sua rede edge usando WASM.
Google Meet
O desfoque de fundo e os fundos virtuais no Google Meet usam WASM com SIMD para processamento de video em tempo real. O modulo WASM processa cada frame de video rapido o suficiente para manter um video fluido a 30fps.
Suporte de navegadores (2026)
| Funcionalidade | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| Core WASM | Completo | Completo | Completo | Completo |
| Threads | Sim | Sim | Sim | Sim |
| SIMD (128 bits) | Sim | Sim | Sim | Sim |
| WasmGC | 119+ | 120+ | 18.2+ | Sim |
| Exception Handling | Sim | Sim | Sim | Sim |
| Memory64 | Sim | Sim | Parcial | Sim |
Todos os navegadores principais suportam totalmente WASM. As funcionalidades mais recentes (WasmGC, Exception Handling) alcancaram ampla disponibilidade.
Referencia de ferramentas
| Ferramenta | Proposito | Instalacao |
|---|---|---|
| wasm-pack | Compilar Rust para WASM, gerar pacotes npm | cargo install wasm-pack |
| wasm-bindgen | Bindings de interoperabilidade Rust/JS (usado pelo wasm-pack) | Dependencia no Cargo.toml |
| wasm-opt | Otimizacao do tamanho do binario (reducao de 50%+) | Parte do Binaryen: brew install binaryen |
| wit-bindgen | Gerar bindings a partir de arquivos WIT | cargo install wit-bindgen-cli |
| Wasmtime | Runtime WASM do lado do servidor (implementacao de referencia WASI) | brew install wasmtime |
| Wasmer | Runtime WASM alternativo com suporte WASI | curl https://get.wasmer.io -sSfL | sh |
| wasm-feature-detect | Deteccao de funcionalidades do navegador em tempo de execucao | npm install wasm-feature-detect |
Otimizar o tamanho do binario
Os binarios WASM podem ser grandes. Veja como reduzi-los:
# Cargo.toml [profile.release] opt-level = "z" # Optimize for size lto = true # Link-time optimization codegen-units = 1 # Better optimization, slower compile strip = true # Strip debug symbols
# Build in release mode wasm-pack build --release --target web # Further optimize with wasm-opt wasm-opt -Oz pkg/image_processor_bg.wasm -o pkg/image_processor_bg.wasm
Um modulo WASM tipico em Rust vai de 500KB para menos de 50KB com essas otimizacoes.
Roteiro para comecar
Conclusao
WebAssembly nao e mais experimental. E uma tecnologia de producao usada por algumas das aplicacoes mais exigentes da web. Desempenho quase nativo, seguranca em sandbox e portabilidade universal - nenhum outro alvo de compilacao oferece as tres coisas.
Voce nao precisa reescrever toda a sua aplicacao em WASM. Comece com uma unica funcao intensiva em CPU - um filtro de imagem, um parser de dados, um calculo fisico - compile para WASM e chame a partir do JavaScript. Meca a diferenca. Depois decida onde mais o WASM pode ajudar.
As ferramentas sao maduras, o suporte dos navegadores e universal e o ecossistema esta crescendo. Se voce escreve em Rust, ja esta a um comando de distancia do navegador.
Checklist para comecar:
- Rust e wasm-pack instalados
- Primeiro modulo WASM compilado e funcionando no navegador
- Interoperabilidade com JavaScript funcionando (chamando WASM a partir do JS)
- Build de release com otimizacoes de tamanho aplicadas
- Desempenho comparado com o equivalente em JavaScript puro
- WASI explorado com Wasmtime para casos de uso do lado do servidor