看了 wasm-pack build --target web 產生的 pkg/ 目錄,搞懂了 JS 膠水程式碼的角色。
wasm-pack 輸出四個檔案:
| 檔案 | 用途 |
|---|---|
.wasm |
編譯後的 WASM 二進位 |
.js |
JS 膠水程式碼(runtime 必須) |
.d.ts |
TypeScript 型別宣告(純靜態,runtime 不用) |
_bg.wasm.d.ts |
原始 WASM exports 的型別宣告 |
.d.ts 不參與執行——它們只給 TypeScript 編譯器做型別檢查用。整個流程不涉及 TypeScript 編譯。
膠水程式碼做兩件事:
1. 載入 WASM:init() 用 WebAssembly.instantiateStreaming 串流編譯 .wasm 檔,邊下載邊編譯。
2. 雙向橋接 WASM 和瀏覽器 API:
-
JS → WASM:處理型別轉換。WASM 只懂數字,所以字串要先編碼成 UTF-8 寫進 WASM 線性記憶體,再傳指標和長度:
export function start(canvas_id, grid_width, grid_height) { const ptr0 = passStringToWasm0(canvas_id, wasm.__wbindgen_malloc, ...); const len0 = WASM_VECTOR_LEN; return wasm.start(ptr0, len0, grid_width, grid_height); } -
WASM → JS:
web_sys的每個呼叫都對應一個 JS import 函式。以 WebGPU 的device.createBuffer()為例,Rust 端呼叫web_sys→ WASM 呼叫 import → JS 膠水程式碼呼叫真正的瀏覽器 API:__wbg_createBuffer_fb1752eab5cb2a7f: function(arg0, arg1) { const ret = arg0.createBuffer(arg1); return ret; }
在 wgpu Game of Life 專案裡,膠水程式碼包含大約 200 個這樣的橋接函式,全部由 wasm-bindgen 在建置時根據 #[wasm_bindgen] 和 web_sys 的使用自動生成。