Deno 中文版 Wasm 入门
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 二进制文件,请使用 Wasm Code Explorer
现在,将 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 中。这个 CLI 工具为通过 wasm-bindgen
在 JavaScript 中调用 Rust crate 生成粘合代码。
首先,确保已安装 Deno 和 Rust (deno -v
, rustup -v
, 和 cargo -v
)。在一个新目录中,创建一个 deno.json
{
"tasks": {
"wasmbuild": "deno run -A jsr:@deno/[email protected]"
}
}
使用 new
参数运行任务
$ deno task wasmbuild new
Task wasmbuild deno run -A jsr:@deno/[email protected] "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.js
lib/rs_lib.js
lib/rs_lib.d.ts
lib/rs_lib.wasm
mod.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来改进将 Rust 导入到 JavaScript 的方式。
最后,这里有一些额外的资源,展示了您可以使用 Wasm 做什么,以及它如何用于改进您的项目
🚨️ Deno 2.1 刚刚发布 🚨️
以及更多!