> 技术文档 > Rust 通用库新增 WebAssembly

Rust 通用库新增 WebAssembly


1 先判断:也许你的 crate 已经能跑 Wasm!

  1. 排查阻碍因素

    • 直接文件/网络 I/O
    • 块式(同步)I/O
    • std::thread 线程创建
    • 并不受支持的 C 系统库绑定
  2. 快速验证

rustup target add wasm32-unknown-unknowncargo build --target wasm32-unknown-unknown

能编译=“理论可用”。要 100% 确认 & 持续可用 → 加入 CI 测试(§6)。

2 添加 Wasm 支持的关键步骤

2.1 把 I/O 从库中“切”出去

浏览器只有 异步 I/O,且无文件系统。
调用者负责获取字节切片,再传给库。

// ❌ 旧:直接读文件pub fn parse_thing(path: &Path) -> Result<MyThing, MyError> { let bytes = std::fs::read(path)?; parse_thing_inner(&bytes)}// ✅ 新:纯逻辑函数 + helperpub fn parse_thing(bytes: &[u8]) -> Result<MyThing, MyError> { /* … */ }pub fn parse_thing_from_file(path: &Path) -> Result<MyThing, MyError> { parse_thing(&std::fs::read(path)?)}

2.2 条件依赖 wasm-bindgen

如果实在要访问 JS 环境(DOM、Fetch 等):

[target.\'cfg(target_arch = \"wasm32\")\'.dependencies]wasm-bindgen = \"0.2\"js-sys = \"0.3\"web-sys = { version = \"0.3\", features = [\"Window\", \"Response\"] }

Tip:把 JS 交互封装进 #[cfg(target_arch = \"wasm32\")] mod js; 中,保持 API 跨平台一致。

2.3 避免 同步 I/O → 拥抱 Future

use futures::Future;pub async fn do_work<F>(reader: F) -> MyOtherThingwhere F: Future<Output = MyThing>,{ let item = reader.await; // …}

在 Web 端 reader 可用 fetch() 实现;在本地可用 Tokio 非阻塞文件读取。

2.4 避免 线程 或让用户“自带线程”

  • 2025 年浏览器已在 跨源隔离 (COOP+COEP) 环境下开放 Wasm 线程,但仍非所有站点都能启用;Safari 仍缺省关闭。([Apryse][1], [queue.acm.org][2])

  • 建议:

    1. #[cfg(target_arch = \"wasm32\")] 禁用线程路径;
    2. 或提供 trait 让调用者决定如何并行。
trait WorkPool { fn spawn<Fut: Future<Output = ()> + \'static + Send>(&self, fut: Fut);}

3 持续集成:保证 永不回退

# .github/workflows/ci.yml 片段- name: Install wasm target run: rustup target add wasm32-unknown-unknown- name: Check compile run: cargo check --target wasm32-unknown-unknown

仅用 cargo check 即可捕获大部分编译错误,速度快。

4 单元测试:Node.js & Headless Browser

  1. 添加依赖

    [dev-dependencies]wasm-bindgen-test = \"0.3\"
  2. 编写测试

    use wasm_bindgen_test::*;wasm_bindgen_test_configure!(run_in_browser);#[wasm_bindgen_test]fn parse_roundtrip() { // …}
  3. 运行

    cargo install wasm-packwasm-pack test --headless --chrome

集成到 CI 后,每次 PR 都能验证浏览器行为。

5 版本管理与生态兼容

组件 2025 推荐版本 说明 wasm-bindgen 0.2.92+ 兼容 Rust 1.77+,支持 Component Model 预览 wasm-pack 0.12.2 新增 --vite 模板,默认生成 ESM wasm-bindgen-futures 0.4.42 与 Future/async 接口对接 wasm-mt (可选) 0.3 简化 Web Worker 线程协调 ([GitHub][3])

6 Checklist

  • cargo check --target wasm32-unknown-unknown 通过
  • I/O 抽象成字节/流;无阻塞调用
  • #[cfg] 屏蔽 std::fs, std::net, std::thread
  • JS 交互封装在 wasm-bindgen 模块
  • CI 添加 wasm 目标 + 浏览器测试
  • 发布前 wasm-pack build --release 验证 npm 包元数据

7 结语

  • 最小可行支持:先让代码 能编;再抽象 I/O、线程,保证 API 稳定。
  • 长期维护:CI 双目标(native & wasm)、浏览器自动测试、定期升级依赖。
  • 未来展望:WASI 0.3 + Component Model 正在进入稳定通道,Rust 生态将进一步简化跨平台发布流程。([Uno Platform][4])

做好以上步骤,你的通用 crate 就能“既跑桌面又跑浏览器”,社区受众瞬间扩大数倍。祝迁移顺利!