WebAssembly — Chạy Code Tốc Độ Native Trên Browser
Giới thiệu WebAssembly (WASM): kiến trúc, cách dùng, use case thực tế và tương lai của WASM trên web.
WebAssembly (WASM) là binary format cho phép chạy code gần tốc độ native trên browser. C, C++, Rust, Go — tất cả compile thành WASM.
WASM Là Gì?#
JavaScript: Viết → Parse → Compile JIT → Run
WebAssembly: Viết (Rust/C++) → Compile → .wasm → Run (gần native)plaintextWASM không thay thế JavaScript — nó bổ sung cho JS ở những tác vụ nặng.
WASM vs JavaScript#
| JavaScript | WebAssembly | |
|---|---|---|
| Performance | Trung bình | Gần native |
| Startup | Parse + JIT warmup | Nhanh (binary format) |
| Use case | UI, logic app | Tính toán nặng, game, xử lý media |
| Memory | GC tự động | Manual (linear memory) |
| DOM access | ✅ | ❌ (phải qua JS) |
Rust + WASM — Hello World#
1. Cài đặt#
# wasm-pack — build tool
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
# Tạo project
cargo new --lib wasm-hellobash2. Cargo.toml#
[package]
name = "wasm-hello"
version = "0.1.0"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"toml3. Code Rust#
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
match n {
0 => 0,
1 => 1,
_ => fibonacci(n - 1) + fibonacci(n - 2),
}
}
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {}! From WebAssembly", name)
}rust4. Build#
wasm-pack build --target webbash5. Dùng trong JS#
import init, { fibonacci, greet } from './pkg/wasm_hello.js';
async function main() {
await init(); // Load .wasm file
console.log(greet('Alice')); // Hello, Alice! From WebAssembly
console.log(fibonacci(40)); // 102334155 — nhanh hơn JS rất nhiều
}
main();typescriptSo Sánh Performance#
// JavaScript
function fibJS(n: number): number {
if (n <= 1) return n;
return fibJS(n - 1) + fibJS(n - 2);
}
// fib(45): JS ≈ 15s, WASM ≈ 1.2s — WASM nhanh hơn ~12xtypescriptUse Case Thực Tế#
1. Xử Lý Ảnh & Video#
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn grayscale(data: &mut [u8]) {
for chunk in data.chunks_mut(4) {
let r = chunk[0] as f32;
let g = chunk[1] as f32;
let b = chunk[2] as f32;
let gray = (0.299 * r + 0.587 * g + 0.114 * b) as u8;
chunk[0] = gray;
chunk[1] = gray;
chunk[2] = gray;
}
}rust2. Nén/Giải Nén#
ffmpeg.wasm — FFmpeg chạy trong browser:
import { FFmpeg } from '@ffmpeg/ffmpeg';
const ffmpeg = new FFmpeg();
await ffmpeg.load();
await ffmpeg.exec(['-i', 'input.mp4', '-vf', 'scale=1280:720', 'output.mp4']);
const data = await ffmpeg.readFile('output.mp4');typescript3. Database Client#
SQLite WASM — SQLite chạy trong browser:
import sqlInit, { Database } from 'sql.js';
const SQL = await sqlInit();
const db = new SQL.Database();
db.run('CREATE TABLE users (id INT, name TEXT)');
db.run('INSERT INTO users VALUES (?, ?)', [1, 'Alice']);
const result = db.exec('SELECT * FROM users');typescript4. Game Engine#
Unity, Unreal Engine export WebGL (dùng WASM). Game chạy trong browser với performance gần native.
Go WASM#
package main
import "syscall/js"
func add(this js.Value, args []js.Value) any {
return args[0].Int() + args[1].Int()
}
func main() {
js.Global().Set("addWasm", js.FuncOf(add))
select {} // Keep running
}goGOOS=js GOARCH=wasm go build -o main.wasmbashWASM Trong Workers#
Dùng WASM trong Cloudflare Workers:
import wasm from './module.wasm';
export default {
async fetch(request: Request): Promise<Response> {
const instance = await WebAssembly.instantiate(wasm);
const result = instance.exports.fibonacci(40);
return new Response(`fib(40) = ${result}`);
},
};typescriptWASI — WebAssembly System Interface#
WASI cho phép WASM chạy outside browser — trên server, CLI, embedded:
Browser: WASM + JS API
Server: WASM + WASI (filesystem, network, clock)plaintextBytecode Alliance phát triển WASI để WASM trở thành runtime phổ quát.
Công Cụ & Framework#
| Công cụ | Mục đích |
|---|---|
| wasm-pack | Build Rust → WASM |
| Emscripten | Build C/C++ → WASM |
| AssemblyScript | TypeScript → WASM |
| Blazor | C# → WASM (Microsoft) |
| Pyodide | Python → WASM |
| wasmtime | WASM runtime (server-side) |
| wasmer | WASM runtime (server-side) |
Hạn Chế#
- Không DOM access — phải qua JS bridge (chi phí)
- Debug khó — chưa có source map hoàn chỉnh
- Bundle size — .wasm file có thể lớn (~MB)
- GC — manual memory management (trừ C#/Go có GC riêng)
Kết Luận#
WASM không thay thế JavaScript — nó là công cụ cho tác vụ nặng:
- Game engine
- Image/video processing
- Compression
- Scientific computing
- Database client (SQLite)
- Porting native libraries
Nếu bạn viết web app thông thường (CRUD, UI) — không cần WASM. Nếu bạn cần performance native trên browser — WASM là câu trả lời.