这是 wasm-pack未发布文档,已发布的文档可在 Rust 和 WebAssembly 主文档网站上找到 。此处记录的功能可能在 wasm-pack 的发布版本中不可用。

src/lib.rs

lib.rs 是模板的主要源文件。名称 lib.rs 通常意味着此 Rust 项目将被编译为库。

它包含三个关键部分

  1. #[wasm_bindgen] 函数
  2. 箱子导入
  3. wee_alloc 可选依赖项

我们将从 lib.rs 中最重要的部分开始 - 两个 #[wasm_bindgen] 函数(您可以在文件底部找到它们)。在许多情况下,这是您需要修改的 lib.rs 的唯一部分。

1. 使用 wasm_bindgen

为了更方便地从 wasm-bindgen 箱子中公开功能,我们可以使用 use 关键字。use 允许我们方便地引用箱子或模块的各个部分。您可以在 本书的这一章 中了解更多关于 Rust 如何让您编写模块化代码的信息。

#![allow(unused)]
fn main() {
use wasm_bindgen::prelude::*;
}

许多箱子包含一个前导,这是一个方便一次导入所有内容的列表。这允许模块的常见功能在没有冗长的前缀的情况下方便地访问。例如,在这个文件中,我们之所以能够使用 #[wasm_bindgen],是因为它被前导引入作用域。

use 末尾的星号表示 wasm_bindgen::prelude 模块(即 wasm_bindgen 箱子内的 prelude 模块)中的所有内容都可以被引用,而无需在前面加上 wasm_bindgen::prelude

例如,#[wasm_bindgen] 也可以写成 #[wasm_bindgen::prelude::wasm_bindgen],虽然不推荐这样做。

1. #[wasm_bindgen] 函数

#[wasm_bindgen] 属性表示它下面的函数将在 JavaScript 和 Rust 中都可访问。

#![allow(unused)]
fn main() {
#[wasm_bindgen]
extern {
    fn alert(s: &str);
}
}

extern 块将外部 JavaScript 函数 alert 导入到 Rust 中。此声明是必须的,以便从 Rust 中调用 alert。通过以这种方式声明它,wasm-bindgen 将为 alert 创建 JavaScript 存根,允许我们在 Rust 和 JavaScript 之间传递字符串。

我们可以看到 alert 函数需要一个类型为 &str 的单个参数 s,即字符串。在 Rust 中,任何字符串文字,例如 "Hello, test-wasm!",都是 &str 类型。因此,alert 可以通过编写 alert("Hello, test-wasm!"); 来调用。

我们知道以这种方式声明 alert,因为这是我们在 JavaScript 中调用 alert 的方式 - 通过向它传递一个字符串参数。

#![allow(unused)]
fn main() {
#[wasm_bindgen]
pub fn greet() {
    alert("Hello, test-wasm!");
}
}

如果我们在没有 #[wasm_bindgen] 属性的情况下编写 greet 函数,那么 greet 将无法在 JavaScript 中轻松访问。此外,我们将无法在 JavaScript 和 Rust 之间本机转换某些类型,例如 &str。因此,#[wasm_bindgen] 属性和之前对 alert 的导入都允许从 JavaScript 中调用 greet

这就是您需要了解的与 JavaScript 交互的所有内容,至少是入门!您可以通过阅读 wasm-bindgen 文档 来了解更多信息!

如果您对其他内容感到好奇,请继续阅读。

2. 箱子组织

#![allow(unused)]
fn main() {
mod utils;
}

此语句声明了一个名为 utils 的新模块,该模块由 utils.rs 的内容定义。等效地,我们可以将 utils.rs 的内容放在 utils 声明中,用以下内容替换该行

#![allow(unused)]
fn main() {
mod utils {
    // contents of utils.rs
}
}

无论哪种方式,utils.rs 的内容都定义了一个名为 set_panic_hook 的公共函数。因为我们将其放在 utils 模块中,所以我们可以通过编写 utils::set_panic_hook() 来直接调用该函数。我们将在 src/utils.rs 中讨论如何以及为什么使用此函数。

#![allow(unused)]
fn main() {
    // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
    // allocator.
    if #[cfg(feature = "wee_alloc")] {
        #[global_allocator]	static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
}

在编译时,这将测试此编译是否启用了 wee_alloc 功能。如果启用了它,我们将根据 wee_alloc 的文档 配置一个全局分配器,否则它将编译成空内容。

正如我们之前所见,[features] 中的 default 向量只包含 "console_error_panic_hook",而不包含 "wee_alloc"。因此,在这种情况下,此块将被替换为空代码,因此将使用默认内存分配器而不是 wee_alloc