我初识 WebAssembly 是当初想要分析某个网站的加密算法,最终定位到了一个 .wasm 文件,没错,这个就是 WebAssembly 的构建产物,能够直接运行在浏览器中。在我当时看来这门技术很先进,不过如今看来绝大多数的 web 应用貌似都没使用上,迄今为止我也只在这个网站中看到使用 WebAssembly 的(也许有很多,只是没实质分析过)。
恰好最近正在接触 Rust,而 Rust 开发 WebAssembly 也非常方便,因此本文算是我对 Rust + WebAssembly 的初探。
有关 WebAssembly 不做过多介绍,你可以到 MDN 中查看相关介绍。本文重点于 Rust + WebAssembly 实践与相关工具,在 Rust and WebAssembly (github.com) 或 https://github.com/rwasm 中查看 rustwasm 相关生态。
使用 wasm-pack 打包 rust 为 wasm 文件
下载 wasm-pack,用于将 rust 代码打包 成 .wasm 文件
cargo install wasm-pack
使用 cargo 有可能无法安装 wasm-pack(笔者就安装不了 openssl-sys),可以到 wasm-pack 官网下载对应的二进制文件进行安装。
构建 rust lib
cargo new --lib hello-wasm
将会创建 rust 库工程,并创建 src/lib.rs。修改为以下内容(先不必在意代码)
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
pub fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
接着在 Cargo.toml 文件中添加 wasm-bindgen 依赖,wasm-bindgen 来提供 JavaScript 和 Rust 类型之间的桥梁,允许 JavaScript 使用字符串调用 Rust API,或调用 Rust 函数来捕获 JavaScript 异常。
[package]
name = "hello-wasm"
version = "0.1.0"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
打包
wasm-pack build
WebAssembly 构建产物将会输出在 pkg 目录下,如下
├─pkg
| ├─.gitignore
| ├─hello_wasm.d.ts
| ├─hello_wasm.js
| ├─hello_wasm_bg.js
| ├─hello_wasm_bg.wasm
| └─hello_wasm_bg.wasm.d.ts
如果想当 npm 包发布的话,可以添加 —scope 参数,将会在 pkg 下生成 package.json 文件用于发布或当做一个 npm 包来使用,这样也可以在前端工程中直接当做一个模块来导入使用。
wasm-pack build --scope mynpmusername
借助 wasm-pack 可以非常轻松的将 rust 打包成 wasm,同时还提供了 js 相关支持。直接打包成 js 可导入的 npm 包,而不是让用户导入 wasm 文件然后通过浏览器 WebAssembly 对象来加载 WebAssembly 代码,其他语言的 WebAssembly 开发也是如此。
此外 rustwasm 还提供了对应的模板 rustwasm/wasm-pack-template,可以帮你省去上面的一系列配置操作,专注于你的 wasm 开发。
运行
由于上面我们已经将其打包成了一个 npm 包,只需要将配置好 package.json 的依赖即可,本地的话可通过下方格式,将 pkg 目录更改为 hello-wasm,并放置在根目录下。
"dependencies": {
"hello-wasm": "file:./hello-wasm"
},