快速开始

快速开始

环境配置

$ curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
$ cargo install cargo-generate
$ npm install npm@latest -g

Backend

$ cargo generate --git https://github.com/rustwasm/wasm-pack-template

项目结构如下所示:

├── Cargo.toml
├── LICENSE_APACHE
├── LICENSE_MIT
├── README.md
└── src
    ├── lib.rs
    └── utils.rs

Cargo.toml 文件指定了 Rust 的包管理器和构建工具 Cargo 的依赖关系和元数据。这个文件预先配置了 wasm-bindgen 依赖关系,一些我们稍后会深入研究的可选依赖关系,以及为生成.wasm 库而正确初始化的 crate 类型。src/lib.rs 文件是我们要编译成 WebAssembly 的 Rust crate 的根。它使用 wasm-bindgen 与 JavaScript 接口。它导入了 window.alert 函数,并导出了 greet Rust 函数,该函数会提醒一个问候信息。

extern crate cfg_if;
extern crate wasm_bindgen;

mod utils;

use cfg_if::cfg_if;
use wasm_bindgen::prelude::*;

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

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

#[wasm_bindgen]
pub fn greet() {
    alert("Hello, wasm-game-of-life!");
}

src/utils.rs 模块提供了一些常用的实用工具,使编译为 WebAssembly 的 Rust 工作变得更容易。我们将在后面的教程中更详细地介绍其中的一些实用工具,比如当我们研究调试 wasm 代码时,但我们现在可以忽略这个文件。我们使用 wasm-pack 来协调以下构建步骤。

  • 确保我们有 Rust 1.30 或更新的版本,并通过rustup安装wasm32-unknown-unknown目标。
  • 通过 “cargo “将我们的 Rust 源编译成 WebAssembly.wasm二进制。
  • 使用 “wasm-bindgen “来生成 JavaScript API,以便使用我们的 Rust 生成的 WebAssembly。

然后运行如下命令:

wasm-pack build

当构建完成后,我们可以在 pkg 目录下找到它的工件,它应该有这些内容。

pkg/
├── package.json
├── README.md
├── hello_world_bg.wasm
├── hello_world.d.ts
└── hello_world.js

.wasm 文件是由 Rust 编译器从我们的 Rust 源代码中生成的 WebAssembly 二进制文件,它包含了所有 Rust 函数和数据的编译到 wasm 版本。它包含了我们所有 Rust 函数和数据的编译到 wasm 版本。例如,它有一个导出的 “greet “函数。.js 文件是由 wasm-bindgen 生成的,它包含了 JavaScript 胶水,用于将 DOM 和 JavaScript 函数导入到 Rust 中,并将 WebAssembly 函数暴露给 JavaScript 一个不错的 API。例如,有一个 JavaScript greet 函数,它包装了从 WebAssembly 模块导出的 greet 函数。现在,这个胶水并没有做什么,但当我们开始在 wasm 和 JavaScript 之间来回传递更多有趣的值时,它将帮助牧羊人将这些值越过边界。

import * as wasm from "./hello_world_bg";

// ...

export function greet() {
  return wasm.greet();
}

.d.ts 文件中包含了 JavaScript 胶水的 TypeScript 类型声明,如果你使用 TypeScript,你可以让你对 WebAssembly 函数的调用进行类型检查,你的 IDE 可以提供自动完成和建议。如果你使用 TypeScript,你可以对 WebAssembly 函数的调用进行类型检查,并且你的 IDE 可以提供自动完成和建议!如果你没有使用 TypeScript,你可以安全地忽略这个文件。如果你没有使用 TypeScript,你可以放心地忽略这个文件。

export function greet(): void;

package.json 文件包含了关于生成的 JavaScript 和 WebAssembly 包的元数据。这被 npm 和 JavaScript 捆绑程序用来确定不同包之间的依赖关系、包名、版本和其他一系列东西。它帮助我们与 JavaScript 工具集成,并允许我们将我们的包发布到 npm。

{
  "name": "hello_world",
  "collaborators": ["Your Name <your.email@example.com>"],
  "description": null,
  "version": "0.1.0",
  "license": null,
  "repository": null,
  "files": ["hello_world_bg.wasm", "hello_world.d.ts"],
  "main": "hello_world.js",
  "types": "hello_world.d.ts"
}

Frontend

$ npm init wasm-app www

hello_world/www/
├── bootstrap.js
├── index.html
├── index.js
├── LICENSE-APACHE
├── LICENSE-MIT
├── package.json
├── README.md
└── webpack.config.js

这个 package.json 预先配置了 webpack 和 webpack-dev-server 的依赖,以及对 hello-wasm-pack 的依赖,它是已经发布到 npm 的 wasm-pack-template 初始包的一个版本。这个文件配置了 webpack 和它的本地开发服务器。它是预先配置好的,你不需要调整这个文件就可以让 webpack 和它的本地开发服务器工作。我们不想使用 npm 的 hello-wasm-pack 包,而是想使用我们本地的 hello_world 包。这将允许我们逐步开发我们的生活游戏程序。

{
  // ...
  "dependencies": {
    "hello_world": "file:../pkg" // Add this line!
    // ...
  }
}
import * as wasm from "hello_world";

wasm.greet();