引言
WebAssembly (Wasm) 正悄然改变前端开发的边界。它让浏览器可以运行接近原生速度的 C/C++、Rust、Python 代码,打开了从前难以想象的应用场景——从图像处理到 3D 渲染再到机器学习推理。

WebAssembly 是什么
WebAssembly 是一种低级的、类汇编的二进制格式,可以在浏览器中以接近原生的速度运行。它不是用来替代 JavaScript 的,而是与 JS 协同工作。
1 2 3 4 5 6 7 8 9 10 11 12 13
| C/C++/Rust/Go 源码 │ ▼ 编译器 (Emscripten/wasm-pack/...) │ ▼ .wasm 二进制文件 │ ▼ JavaScript 加载和调用 │ ▼ 浏览器 WASM 虚拟机
|
性能对比
| 任务 |
JavaScript |
WebAssembly |
加速比 |
| Fibonacci(45) |
8500ms |
420ms |
~20x |
| 图像滤镜 |
120ms |
15ms |
~8x |
| JSON 解析 |
45ms |
8ms |
~5.6x |
| AES 加密 |
380ms |
35ms |
~10x |
用 C 语言创建 Wasm 模块
环境搭建
1 2 3 4 5 6
| git clone https://github.com/emscripten-core/emsdk.git cd emsdk ./emsdk install latest ./emsdk activate latest source ./emsdk_env.sh
|
编写 C 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <math.h> #include <emscripten.h>
EMSCRIPTEN_KEEPALIVE int fibonacci(int n) { if (n <= 1) return n; return fibonacci(n - 1) + fibonacci(n - 2); }
EMSCRIPTEN_KEEPALIVE double compute_mandelbrot(double cx, double cy, int max_iter) { double x = 0, y = 0; int iter; for (iter = 0; iter < max_iter; iter++) { double x2 = x * x, y2 = y * y; if (x2 + y2 > 4.0) break; y = 2 * x * y + cy; x = x2 - y2 + cx; } return (double)iter / max_iter; }
|
编译
1 2 3 4 5 6
| emcc math.c -o math.js \ -s WASM=1 \ -s EXPORTED_FUNCTIONS='["_fibonacci", "_compute_mandelbrot"]' \ -s EXPORTED_RUNTIME_METHODS='["cwrap"]' \ -O3
|
JavaScript 调用
1 2 3 4 5 6 7 8 9 10 11
| async function loadWasm() { const Module = await import('./math.js');
const fibonacci = Module.cwrap('fibonacci', 'number', ['number']); const mandelbrot = Module.cwrap('compute_mandelbrot', 'number', ['number', 'number', 'number']);
console.log('Fibonacci(40):', fibonacci(40)); console.log('Mandelbrot:', mandelbrot(-0.7, 0.27, 1000)); }
|
用 Rust 创建 Wasm 模块
环境搭建
1 2 3 4 5 6
| cargo install wasm-pack
cargo new --lib wasm-image-processor cd wasm-image-processor
|
编写 Rust 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| use wasm_bindgen::prelude::*; use web_sys::ImageData;
#[wasm_bindgen] pub fn grayscale(image_data: &mut [u8]) { for chunk in image_data.chunks_mut(4) { let gray = (chunk[0] as f32 * 0.299 + chunk[1] as f32 * 0.587 + chunk[2] as f32 * 0.114) as u8; chunk[0] = gray; chunk[1] = gray; chunk[2] = gray; } }
|
编译和使用
1
| wasm-pack build --target web
|
1 2 3 4 5 6 7 8 9 10 11 12
| import init, { grayscale } from './pkg/wasm_image_processor.js';
async function applyGrayscale() { await init();
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
grayscale(imageData.data); ctx.putImageData(imageData, 0, 0); }
|
在浏览器中运行 Python
Pyodide
Pyodide 将 CPython 解释器编译成了 WebAssembly,让你可以在浏览器中运行 Python 和科学计算库。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <script src="https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.js"></script> <script> async function main() { let pyodide = await loadPyodide();
await pyodide.loadPackage('numpy');
let result = pyodide.runPython(` import numpy as np
# 矩阵运算 a = np.array([[1, 2, 3], [4, 5, 6]]) b = np.array([[7, 8], [9, 10], [11, 12]]) c = np.dot(a, b)
# 返回结果 c.tolist() `);
console.log('矩阵乘法结果:', result.toJs()); }
main(); </script>
|
SIMD 和线程支持
SIMD 加速
1 2 3 4 5 6 7 8 9 10 11 12
| #include <wasm_simd128.h> #include <emscripten.h>
EMSCRIPTEN_KEEPALIVE void add_arrays_simd(float* a, float* b, float* result, int len) { for (int i = 0; i < len; i += 4) { v128_t va = wasm_v128_load(&a[i]); v128_t vb = wasm_v128_load(&b[i]); v128_t vresult = wasm_f32x4_add(va, vb); wasm_v128_store(&result[i], vresult); } }
|
编译时启用 SIMD:
1
| emcc simd.c -o simd.js -msimd128 -O3
|
共享内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const memory = new WebAssembly.Memory({ initial: 256, maximum: 512, shared: true, });
const importObject = { env: { memory } };
const wasm = await WebAssembly.instantiate(wasmBytes, importObject); const wasmMemory = new Float64Array(memory.buffer);
for (let i = 0; i < 100000; i++) { wasmMemory[i] = Math.random(); }
wasm.instance.exports.process_array(0, 100000);
|
实际应用场景
| 场景 |
技术方案 |
效果 |
| 图片压缩 |
C++ 编译 Wasm + SIMD |
比 JS 快 20x |
| Figma 的矢量渲染 |
C++ → Wasm |
复杂图形流畅 60fps |
| AutoCAD Web |
30 年 C++ 代码库 → Wasm |
完整 CAD 引擎在浏览器中运行 |
| TensorFlow.js Wasm 后端 |
Wasm + SIMD + 多线程 |
使浏览器端 ML 推理可实用 |
| Google Earth Web |
C++ → Wasm |
3D 地图流畅渲染 |
调试工具
1 2 3 4
| wasm2wat module.wasm -o module.wat
|
Chrome DevTools 现在支持加载 .wasm 源码映射,可以直接在浏览器中调试 C/C++ 源码。
WASI:走出浏览器的 Wasm
WebAssembly System Interface (WASI) 让 Wasm 在浏览器之外也能运行:
1 2 3 4 5
| wasmtime hello.wasm
wasmedge hello.wasm
|
1 2 3 4 5 6 7 8 9
| #[tokio::main] async fn main() -> Result<()> { let response = reqwest::get("https://api.example.com/data").await?; let data: serde_json::Value = response.json().await?; println!("{}", data); Ok(()) }
|
编译:
1 2
| cargo build --target wasm32-wasi wasmtime target/wasm32-wasi/debug/app.wasm
|
总结
WebAssembly 正在打破「前端只能用 JavaScript」的天花板。它让现有的 C/C++/Rust 代码库可以直接运行在浏览器中,也让前端能够胜任更复杂的计算任务。
Wasm 不会取代 JavaScript,但会成为前端工具箱中最锋利的刀——处理计算密集型任务时的不二之选。