wasm-pack 是 Rust 生态中专门用于构建 WebAssembly 模块的高效工具,其核心在于整合 rustc、wasm-bindgen 等工具链,实现 Rust 代码到 Wasm 模块的无缝转换。
它通过解析 Cargo.toml 配置,自动生成 JavaScript 胶水代码(Glue Code),解决 Rust 与 JavaScript 之间的数据类型映射和函数调用问题,同时确保编译后的 Wasm 模块符合 Web 标准规范,支持在浏览器和 Node.js 环境中运行。
尝试一下
安装好 Rust 工具链后,接下来我们需要安装wasm-pack,它是将 Rust 代码编译、打包为 Wasm 模块,并自动生成 JavaScript 调用接口的核心工具。使用cargo安装wasm-pack非常简单,在终端中执行以下命令::
cargo install wasm-pack
cargo 会自动从 crates.io 下载wasm-pack并安装到本地。安装完成后,执行wasm-pack --version命令,验证是否安装成功。如果能显示wasm-pack的版本号,说明安装成功。
创建 Rust 项目
使用cargo创建项目非常方便,在终端中执行以下命令:
cargo new --lib hello_wasm
cd hello_wasm
这两条命令会在当前目录下创建一个名为hello_wasm的新目录,并在其中初始化一个新的 Rust 库项目。--lib参数表示我们创建的是一个库项目,而不是可执行项目。进入hello_wasm目录后,你会看到项目目录结构如下:
Cargo.toml是项目的配置文件,用于管理项目的依赖和元数据;src/lib.rs是项目的源代码文件,Rust 代码就写在这里。
配置 Cargo.toml
打开Cargo.toml文件,添加以下内容:
[package]
name = "hello_wasm"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
[lib]部分告诉 Cargo 我们要生成一个动态链接库(cdylib),这是 WebAssembly 所需要的格式。
[dependencies]部分添加了wasm-bindgen依赖,它是 Rust 与 JavaScript 之间进行交互的重要工具,版本号0.2表示我们使用的是 0.2 版本的wasm-bindgen。
添加依赖后,Cargo 会自动下载并管理这些依赖。
编写 Rust 逻辑(src/lib.rs)
打开src/lib.rs文件,编写以下代码:
use wasm_bindgen::prelude::*;
// 使用#[wasm_bindgen]宏将函数导出为JavaScript可调用的接口
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!(
"Hello, {}! Welcome to the world of Rust and WebAssembly.",
name
)
}
在这段代码中,我们首先导入了wasm_bindgen::prelude::*,这是使用wasm_bindgen的必要步骤,它包含了一些常用的宏和类型定义。
然后,我们定义了一个greet函数,这个函数接受一个字符串类型的参数name,并返回一个格式化后的问候语字符串。
#[wasm_bindgen]宏将这个函数标记为可以被 JavaScript 调用的接口,这样在编译后,我们就可以在 JavaScript 中调用这个函数了。
编译为 Wasm 模块
编写好 Rust 代码后,接下来我们使用wasm-pack将其编译为 Wasm 模块,并生成 JavaScript 调用接口。在项目根目录下的终端中执行以下命令:
wasm-pack build --target web
wasm-pack build命令会将 Rust 代码编译为 Wasm 模块,并生成相应的 JavaScript 胶水代码和类型声明文件。
--target web参数表示我们生成的 Wasm 模块是用于 Web 环境的。
编译完成后,项目目录下会生成一个pkg目录,里面包含了编译后的文件:
其中,hello_wasm_bg.wasm是 WebAssembly 字节码文件,它包含了我们编写的 Rust 代码编译后的机器码,是在浏览器中实际执行的代码。
hello_wasm.js是 JavaScript 调用接口文件,它提供了在 JavaScript 中调用 Wasm 模块的方法,通过这个文件,可以在 JavaScript 中轻松地调用 Rust 编写的函数。
接下来,我们创建一个 HTML 页面来调用编译好的 Wasm 模块。在项目根目录下创建一个index.html
文件,编写以下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Rust Wasm Hello World</title>
</head>
<body>
<script type="module">
// 导入Wasm模块的初始化函数和导出的greet函数
import init, { greet } from './pkg/hello_wasm.js'
// 初始化Wasm模块
init().then(() => {
// 调用Rust导出的greet函数,并传入参数"WebAssembly"
const message = greet('WebAssembly')
// 在控制台输出问候语
console.log(message)
// 也可以将问候语显示在页面上,例如创建一个段落元素并添加到页面中
const p = document.createElement('p')
p.textContent = message
document.body.appendChild(p)
})
</script>
</body>
</html>
在这段 HTML 代码中,我们首先通过<script type="module">标签引入了pkg/hello_wasm.js文件,这是wasm-pack生成的 JavaScript 调用接口文件。
然后,我们调用init()函数来初始化 Wasm 模块,这个函数会加载并实例化hello_wasm_bg.wasm文件。
初始化完成后,我们调用greet('WebAssembly')函数,传入参数WebAssembly,并将返回的问候语字符串打印到控制台,同时也通过创建段落元素的方式将问候语显示在页面上。
用server启动这个:
打开启动后的页面: