Introdução ao WebAssembly e seu papel no Node.js
\n\nWebAssembly (WASM) é um formato binário de instruções de baixo nível que é executado em uma máquina virtual com desempenho quase nativo. No ecossistema Node.js, o WebAssembly abre novos horizontes: permite executar código escrito em C, C++, Rust ou Go diretamente no ambiente do servidor. Isso é especialmente relevante para tarefas que exigem alto desempenho: processamento de imagens, criptografia, análise de dados, trabalho com grandes arrays de números.
\n\nNeste artigo, abordaremos o ciclo completo de trabalho com WebAssembly no Node.js: desde a compilação do código-fonte até a integração do módulo pronto em uma aplicação JavaScript.
\n\nConceitos básicos e preparação do ambiente
\n\nO que você precisa saber antes de começar
\nUm módulo WebAssembly é um arquivo binário com extensão .wasm. Ele não tem acesso direto ao DOM ou ao sistema de arquivos — toda interação ocorre por meio de "funções importadas" que você passa do JavaScript. No Node.js, essa limitação é contornada com wrappers especiais.
Instalação das ferramentas
\nPara compilar código para WASM, precisamos do Emscripten SDK. Instalação no Linux/macOS:
\ngit clone https://github.com/emscripten-core/emsdk.git\ncd emsdk\n./emsdk install latest\n./emsdk activate latest\nsource ./emsdk_env.sh\n\nPara projetos Rust, use wasm-pack:
npm install -g wasm-pack\n\nCriação e compilação do primeiro módulo WASM
\n\nExemplo em C — função de soma
\nVamos criar uma função simples em C que soma dois números:
\n// math.c\n#include <emscripten.h>\n\nEMSCRIPTEN_KEEPALIVE\nint add(int a, int b) {\n return a + b;\n}\n\nEMSCRIPTEN_KEEPALIVE\nint multiply(int a, int b) {\n return a * b;\n}\n\nCompilando para WASM com Emscripten:
\nemcc math.c -o math.js -s EXPORTED_FUNCTIONS="['_add', '_multiply']" -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME="createMathModule"\n\nNa saída, obtemos dois arquivos: math.wasm e math.js — um wrapper para carregamento.
Carregando o módulo no Node.js
\nAgora vamos usar o módulo em JavaScript:
\n// index.js\nconst createMathModule = require('./math.js');\n\ncreateMathModule().then(module => {\n const add = module._add;\n const multiply = module._multiply;\n\n console.log('5 + 3 =', add(5, 3)); // 8\n console.log('4 * 7 =', multiply(4, 7)); // 28\n});\n\nExecutando:
\nnode index.js\n\nTrabalhando com memória e tipos de dados complexos
\n\nPassagem de strings e arrays
\nWASM opera apenas com números. Para passar strings ou arrays, é necessário alocar memória na memória linear do módulo. Vamos considerar um exemplo em C que recebe uma string e retorna seu comprimento:
\n// string_ops.c\n#include <string.h>\n#include <emscripten.h>\n\nEMSCRIPTEN_KEEPALIVE\nint string_length(char* str) {\n return strlen(str);\n}\n\nEMSCRIPTEN_KEEPALIVE\nvoid to_upper(char* str) {\n for (int i = 0; str[i]; i++) {\n if (str[i] >= 'a' && str[i] <= 'z') {\n str[i] -= 32;\n }\n }\n}\n\nCompilando:
\nemcc string_ops.c -o string_ops.js -s EXPORTED_FUNCTIONS="['_string_length', '_to_upper']" -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME="createStringModule"\n\nCódigo JavaScript para trabalhar com memória:
\nconst createStringModule = require('./string_ops.js');\n\ncreateStringModule().then(module => {\n const { _string_length, _to_upper, heap } = module;\n \n // Aloca memória para a string\n const input = "hello world";\n const ptr = module._malloc(input.length + 1);\n \n // Copia a string para a memória WASM\n for (let i = 0; i < input.length; i++) {\n heap[i + ptr] = input.charCodeAt(i);\n }\n heap[ptr + input.len