Rust代码使用wasm-pack打包为wasm,WebAssembly加速

28 阅读4分钟

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启动这个:

打开启动后的页面: