JavaScript 是一种脚本语言,与 CPU 实际执行的机器码相距甚远。不过,JavaScript 也有一种执行二进制机器码——或者接近机器码的东西——的方式:WebAssembly。WebAssembly 简称 Wasm,是一种底层、可移植的二进制格式,可以在浏览器中以接近原生的速度运行。
Wasm 是 C、C++ 和 Rust 等语言的编译目标,让 Google Earth、Photoshop 这类高性能应用能够直接在浏览器中运行。原文认为,严格的沙箱隔离也赋予它较高的安全性,使其适合金融、医疗等敏感应用。随着 Deno 2.1 提供一等 Wasm 支持,使用 Wasm 模块变得更加简单。
下面将构建一个简单的 Wasm 模块,并通过它从 JavaScript 调用 Rust。
构建 Wasm 模块
先构建一个简单的 Wasm 模块,再将它导入 Deno。
从一个名为 add 的小函数开始,使用 WebAssembly 文本格式编写。新建 add.wat 文件,并添加以下内容:
(module
(func (export "add") (param $a i32) (param $b i32) (result i32)
local.get $a
local.get $b
i32.add
)
)
使用 wat2wasm 将它编译成 add.wasm:
wat2wasm add.wat
可以使用 Wasm Code Explorer 查看生成的 Wasm 二进制文件:

现在,将 add.wasm 导入 Deno:
import { add } from "./add.wasm";
console.log(add(1, 2));
原文给出的输出如下:
> deno run main.ts 3
Deno 导入 Wasm 时能够理解模块的导出,并对它们进行类型检查。有关导入 Wasm 的更多信息,请参阅文档。
这个例子很简单,但在大多数生产场景中,人们会把 Rust、C++ 或 Go 编译为 Wasm,而不是手写 wat。
通过 Wasm 从 JavaScript 调用 Rust
接下来,使用 wasmbuild 将 Rust 函数导入 JavaScript。这个命令行工具通过 wasm-bindgen 生成胶水代码,让 JavaScript 可以调用 Rust crate。
首先确认已经安装 Deno 和 Rust(可用 deno -v、rustup -v 和 cargo -v 检查)。在一个新目录中创建 deno.json:
{
"tasks": {
"wasmbuild": "deno run -A jsr:@deno/wasmbuild@0.19.0"
}
}
带上 new 参数运行任务:
$ deno task wasmbuild new Task wasmbuild deno run -A jsr:@deno/wasmbuild@0.19.0 "new" Creating rs_lib... To get started run: deno task wasmbuild deno run mod.js
该命令会在 rs_lib 中生成 Rust crate 的脚手架,其中包含示例函数和测试:
// rs_lib/src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[wasm_bindgen]
pub struct Greeter {
name: String,
}
#[wasm_bindgen]
impl Greeter {
#[wasm_bindgen(constructor)]
pub fn new(name: String) -> Self {
Self { name }
}
pub fn greet(&self) -> String {
format!("Hello {}!", self.name)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_adds() {
let result = add(1, 2);
assert_eq!(result, 3);
}
#[test]
fn it_greets() {
let greeter = Greeter::new("world".into());
assert_eq!(greeter.greet(), "Hello world!");
}
}
这个文件定义了 add 函数:接收两个有符号整数,返回一个有符号整数;还定义了带有两个方法的 Greeter 结构体。通过 #[wasm_bindgen] 属性,它们被导出供 JavaScript 使用。
你可以在这里编写自己的 Rust 代码;本例继续使用生成的代码。
接着运行 wasmbuild 任务来构建项目:
$ deno task wasmbuild
这会生成以下文件:
lib/rs_lib.internal.jslib/rs_lib.jslib/rs_lib.d.tslib/rs_lib.wasmmod.js
我们可以通过 Wasm Code Explorer 查看生成的 Wasm 二进制文件 lib/rs_lib.wasm:

现在导入模块。上面列出的最后一个文件 mod.js,实际上已经包含了从 JavaScript 导入 Rust 函数的示例:
import { add, Greeter } from "./lib/rs_lib.js";
// adds
console.log(add(1, 1));
// greets
const greeter = new Greeter("world");
console.log(greeter.greet());
这段代码导入并执行 add 和 Greeter。它们原本在 Rust 中定义,经编译和胶水代码封装后可从 JavaScript 调用。原文使用 deno mod.js 尝试运行:
$ deno mod.js 2 Hello world!
原文示例成功运行了!
想进一步了解 Rust 与 JavaScript 的结合?请阅读用 Rust 构建自己的 JavaScript 运行时。
接下来呢?
希望这份循序渐进的 WebAssembly 入门,不仅展示了怎样在 JavaScript 和浏览器中使用它,也能给你带来一些潜在用途的灵感。
在 Deno 2.1 中,导入 Wasm 模块与导入普通 JavaScript 模块一样容易。对于 Rust,作者计划通过简化 Wasm 编译步骤,并仅暴露更高层的 JavaScript API,进一步改善 wasmbuild 的 Rust 到 JavaScript 导入体验。
最后,下面这些资源展示了 Wasm 的能力,以及如何用它改进项目:
以及更多功能!
来源与版权
原文作者:Andy Jiang、David Sherret。来源:Deno Blog,2025-01-28。依用户已声明的转载授权译载;作者署名与原文链接保留。原页面没有单独列出本文的许可文本,不据此推定为公共领域。 阅读原文。











暂无评论内容