文章摘要
作者分享使用Rust编写Wasm的经验,建议通过引用传递数据、优先使用Rc
文章总结
WebAssembly 开发实践笔记
作者分享了几年来使用 Rust 编写 WebAssembly(Wasm) 的经验总结,重点介绍了如何优化与 wasm-bindgen 工具协作的开发模式。
核心建议
- 引用传递优先:通过
&reference传递跨边界数据 - 避免可变引用:使用
Rc<RefCell<T>>或Arc<Mutex<T>>替代&mut - 类型设计:
- 不要为导出类型派生
Copytrait - 对集合中的跨边界类型使用
wasm_refgen - Rust 导出类型添加
Wasm前缀,JS 端使用无前缀名称 - JS 导入类型添加
Js前缀
- 不要为导出类型派生
- 错误处理:为所有 Rust 导出错误类型实现
From<YourError> for JsValue
技术细节
内存模型差异
JavaScript 和 Rust 采用不同的内存管理方式: - JavaScript:垃圾回收、可重入、异步 - Rust:显式所有权、借用规则
类型命名规范
- 基本类型:实现
IntoWasmAbi的原始类型 - Rust 导出类型:添加
Wasm前缀(如WasmFoo) - JS 导入类型:添加
Js前缀(如JsCharacter)
引用传递的重要性
直接消费跨边界值会导致 JS 端句柄失效。推荐使用 Rc<RefCell<T>> 等内部可变性模式。
集合处理技巧
通过 duck typing 解决 wasm-bindgen 对集合类型的限制: 1. 使导出类型易于克隆 2. 暴露命名空间化的克隆方法 3. 通过 JS 接口导入该方法 4. 实现便捷的类型转换
错误处理优化
将 Rust 错误转换为 js_sys::Error 以保留错误信息:
rust
impl From<WasmError> for JsValue {
fn from(err: WasmError) -> Self {
let js_err = js_sys::Error::new(&err.to_string());
js_err.set_name("ErrorType");
js_err.into()
}
}
实用技巧
- 构建信息打印:在启动时输出 Git 哈希和构建状态,便于调试
- wasm_refgen 工具:简化引用生成代码的编写
- 避免
Copytrait:防止意外复制资源句柄
总结
作者强调明确处理 Wasm 边界的重要性,建议采用清晰的命名约定、引用传递和 duck typing 等技术来克服 wasm-bindgen 的限制,从而提升 Rust+Wasm 的开发体验。
注:本文内容基于作者个人实践经验,可能存在更优解决方案。作者对 wasm-bindgen 维护者的工作表示敬意。
评论总结
以下是评论内容的总结:
1. 对WASM的失望与批评
内容不符预期:多位用户指出文章标题与实际内容不符,期待的是直接编写WASM的指南,而非Rust工具链相关内容。
引用:
"I was hoping to find Notes on Writing WASM, instead I found stuff for writing Rust to target WASM" (评论1)
"I expected an article about writing code directly in wasm. Title is bit missleading" (评论9)复杂性与工具链问题:批评WASM生态过于依赖Rust工具链,且自动绑定生成(如
wasm_bindgen)增加了不必要的复杂性。
引用:
"Yes wasm is basically a rust thing at this point unfortunately" (评论5)
"It adds an incredible amount of complexity and bloat" (评论6)类型转换与性能损耗:指出WASM与JavaScript类型系统(如UTF-8与UTF-16)不匹配导致频繁转换,影响性能。
引用:
"We need to constantly convert between them" (评论2)
2. WASM的定位与前景争议
小众化担忧:部分用户认为WASM可能永远是小众技术,实际使用者极少。
引用:
"wasm will remain a small niche... probably forever" (评论3)应用场景偏离初衷:批评WASM从高性能计算工具演变为通用沙箱方案,导致臃肿化。
引用:
"Now it gets marketed as something to write sandboxed code/components for every language" (评论2)
3. 开发体验与语言对比
多语言实践反馈:用户分享使用C++、Zig、Odin和Rust开发WASM游戏的体验,指出Rust的严格性在快速开发中成为障碍,而Odin体验最佳。
引用:
"Rust is an authoritarian nanny state" (评论12)
"Odin, I found surprisingly pleasant... Nicest I’ve seen by far" (评论12)工具改进建议:推荐实用工具(如
tsify)提升类型安全,并建议手动设计C API而非依赖自动绑定。
引用:
"A tool that’s great to have... is tsify" (评论8)
"tunnel through a properly designed C API" (评论6)
4. 技术改进与未来展望
规范与生态进步:肯定WASM规范清晰,且Firefox正推动更高层次的API接口提案。
引用:
"I found the spec very clear and well-written" (评论11)
"Firefox is pushing an early proposal to expose all the web apis directly to wasm" (评论14)GC语言支持疑问:探讨GC语言(如Java)在WASM中的适用性是否改善。
引用:
"Is anyone using WASM with GC languages?" (评论13)
总结呈现了WASM在工具链、类型系统、生态定位等方面的争议,同时包含开发者实践反馈和技术演进动态,观点较为平衡。