前幾天我們把功能越寫越多(多個濾鏡、錯誤格式、Worker 版…),結果 pkg/*.wasm
越來越胖。今天把體重管理講清楚:哪裡在長肉、誰負責減肥、怎麼操作。其實就是把 Cargo/LLVM 做「Rust→機器碼階段」的最佳化,wasm-opt 做二次瘦身。
wasm-pack build
預設是 dev(無 LTO、較少最佳化、帶除錯資訊)。panic!
/ format!
會把一大坨 core::fmt
、展開流程拉進來。web-sys
/ serde
/ 其他 crates 的「全功能」常把用不到的符號也編進來。wasm-bindgen
產生的 glue/型別描述若不最小化,也會占空間。ls -lh pkg/*.wasm
cargo install twiggy
→ twiggy top pkg/xxx_bg.wasm
(誰佔最大)wasm-tools size pkg/xxx_bg.wasm
(各 section 大小)du -h pkg/*
(glue + wasm)在 Cargo.toml
加下列 release 組態:
# Cargo.toml
[profile.release]
opt-level = "z" # 比 "s" 更追求小
lto = "fat" # 跨 crate 最佳化,通常顯著變小
codegen-units = 1 # 讓 LLVM 看得到整體(更好 DCE/內聯)
panic = "abort" # 砍掉 unwind 機制與相關表
strip = "symbols" # 去除符號(Rust 1.70+ 穩定),或用 true 也行
debug = false # 確保不帶 DWARF
[dependencies]
# 盡量關掉不需要的 default features
serde = { version = "1", default-features = false, features = ["derive"] }
serde-wasm-bindgen = "0.6"
wasm-bindgen = { version = "0.2", default-features = false }
# web-sys / js-sys 只開用到的功能(如果有用到才加)
# web-sys = { version = "0.3", features = ["Window"] }
程式碼層的小調整(只新增的部分):
// 在 lib.rs 最上面:release 版不要掛 panic hook,避免拉進 fmt
#[cfg(debug_assertions)]
#[wasm_bindgen(start)]
pub fn set_panic_hook() {
console_error_panic_hook::set_once();
}
// 錯誤訊息盡量用短字串;避免 format! 拼長句(會拉進 core::fmt)
Tip:f32 足夠時別用 f64;不要濫用 Debug/Display;可把大型常數表改為運算生成或壓縮儲存。
wasm-opt
是 Binaryen 的工具,對已產出的 .wasm做 peephole/DCE/inline/合併基本塊/剝除區段等。
最常用一條:
# 安裝:brew install binaryen 或 npm i -g binaryen
wasm-opt -Oz --strip-debug --strip-producers -o pkg/xxx_bg.wasm pkg/xxx_bg.wasm
Oz
:極致瘦身(比 Os
更激進)。-strip-debug --strip-producers
:移除除錯/編譯器資訊。Os
;想更狠可加 -dce --merge-blocks --vacuum
(通常 Oz
已涵蓋)。wasm-pack 會自動幫你跑 wasm-opt(如果系統有裝):用
wasm-pack build --target web --release
就會觸發。沒裝的話,自己補跑一次上面那條。
# 1) 乾淨重建
rm -rf pkg target
wasm-pack build --target web --release # 若裝了 binaryen,會自動調用 wasm-opt
# 2) 若沒自動跑到 wasm-opt,再補刀一次
wasm-opt -Oz --strip-debug --strip-producers \
-o pkg/rustwasm_test_bg.wasm pkg/rustwasm_test_bg.wasm
# 3) 檢查體積
ls -lh pkg/*.wasm
# 4) 看熱點
twiggy top pkg/rustwasm_test_bg.wasm | head -n 20