blog.dopana

Back

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)
plaintext

WASM không thay thế JavaScript — nó bổ sung cho JS ở những tác vụ nặng.

WASM vs JavaScript#

JavaScriptWebAssembly
PerformanceTrung bìnhGần native
StartupParse + JIT warmupNhanh (binary format)
Use caseUI, logic appTính toán nặng, game, xử lý media
MemoryGC tự độngManual (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-hello
bash

2. Cargo.toml#

[package]
name = "wasm-hello"
version = "0.1.0"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"
toml

3. 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)
}
rust

4. Build#

wasm-pack build --target web
bash

5. 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();
typescript

So 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 ~12x
typescript

Use 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;
    }
}
rust

2. 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');
typescript

3. 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');
typescript

4. 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
}
go
GOOS=js GOARCH=wasm go build -o main.wasm
bash

WASM 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}`);
  },
};
typescript

WASI — 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)
plaintext

Bytecode 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-packBuild Rust → WASM
EmscriptenBuild C/C++ → WASM
AssemblyScriptTypeScript → WASM
BlazorC# → WASM (Microsoft)
PyodidePython → WASM
wasmtimeWASM runtime (server-side)
wasmerWASM 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.

Tài liệu tham khảo#