使用 Rust 编译成 WebAssembly (WASM) 模块并与 JavaScript 协同工作

567 阅读4分钟

使用 Rust 编译成 WebAssembly (WASM) 模块并与 JavaScript 协同工作,是构建高性能 Web 应用的一种常见做法。这个过程通常涉及以下几个步骤:

  1. 安装 Rust 工具链和 wasm 工具
  2. 编写 Rust 代码
  3. 将 Rust 编译为 WASM
  4. 通过 JavaScript 加载和交互 WASM 模块

步骤 1: 安装 Rust 和相关工具

首先,你需要安装 Rust 和一些必要的工具:

安装 Rust 工具链

  1. 安装 Rust: 打开终端,运行以下命令:

    bash
    复制代码
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    

    这会安装最新的 Rust 版本和相关工具。

  2. 安装 wasm-packwasm-pack 是一个工具,能够帮助将 Rust 代码编译为 WASM 模块,并方便与 JavaScript 交互。

    bash
    复制代码
    cargo install wasm-pack
    
  3. 安装 wasm32-unknown-unknown 目标: WebAssembly 需要特定的目标来进行编译。

    bash
    复制代码
    rustup target add wasm32-unknown-unknown
    
  4. 安装 npmwebpack(如果你想用现代的前端工具构建项目): WebAssembly 通常与现代 JavaScript 工具链一起使用(如 webpack),如果你还没有安装这些工具,可以通过 npm 安装:

    bash
    复制代码
    npm install -g webpack webpack-cli
    

步骤 2: 编写 Rust 代码

创建一个新的 Rust 项目并编写代码。

  1. 初始化 Rust 项目: 在终端中运行以下命令来创建一个新的 Rust 项目:

    bash
    复制代码
    cargo new rust-wasm-example --lib
    cd rust-wasm-example
    
  2. 编写 Rust 代码: 在 src/lib.rs 中编写你希望编译成 WASM 的 Rust 代码。例如,下面的代码是一个简单的加法函数:

    rust
    复制代码
    use wasm_bindgen::prelude::*;
    
    // This is the entry point for JavaScript
    #[wasm_bindgen]
    pub fn add(a: i32, b: i32) -> i32 {
        a + b
    }
    
    // The following function is for the web
    #[wasm_bindgen]
    pub fn greet(name: &str) {
        web_sys::console::log_1(&format!("Hello, {}!", name).into());
    }
    

    这里的代码使用了 wasm_bindgen 库,该库允许 Rust 与 JavaScript 交互。wasm_bindgen 是一个 Rust 库,它使得 Rust 可以暴露给 JavaScript 使用。

  3. 添加 wasm-bindgen 依赖: 在 Cargo.toml 文件中,添加 wasm-bindgen 作为依赖:

    toml
    复制代码
    [dependencies]
    wasm-bindgen = "0.2"
    
  4. 编写 JavaScript 代码(如需要): 如果你希望与浏览器的 API(如 console)进行交互,可以用 web-sys 库,或者其他 Web API 库。

    Cargo.toml 中添加依赖:

    toml
    复制代码
    [dependencies]
    web-sys = "0.3"
    wasm-bindgen = "0.2"
    

步骤 3: 使用 wasm-pack 编译 Rust 代码为 WASM

  1. 运行 wasm-pack 编译 Rust 代码: 你可以使用 wasm-pack 来构建和打包你的 Rust 代码:

    bash
    复制代码
    wasm-pack build --target web
    

    --target web 标志指定 WASM 目标是浏览器。此命令将编译 Rust 代码,并生成一个适合 Web 使用的 .wasm 文件,同时还会创建一个 JavaScript 包装文件,允许你方便地在浏览器中使用 WASM。

  2. 查看生成的文件: 编译后,wasm-pack 会生成以下文件和目录:

    • pkg/ 目录:包含了生成的 *.wasm 文件和一个 JavaScript 包装器文件。
    • package.json 文件:包含 JavaScript 模块信息。

步骤 4: 使用 JavaScript 调用 WASM 模块

  1. 设置 JavaScript 项目: 在 pkg/ 目录下,你会看到生成的 JavaScript 包装器。你可以将其集成到一个新的 Web 项目中。

    首先,在你的 Web 项目中初始化一个 npm 项目:

    bash
    复制代码
    mkdir wasm-web
    cd wasm-web
    npm init -y
    
  2. 安装依赖: 安装 wasm-bindgenwebpack

    bash
    复制代码
    npm install --save webpack webpack-cli
    npm install --save ./path-to-rust-project/pkg  # 引用 Rust 编译的包
    
  3. 编写前端 JavaScript 代码: 创建一个简单的 HTML 和 JavaScript 文件来加载并使用 WASM 模块。

    index.html

    html
    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>WASM with Rust</title>
    </head>
    <body>
      <h1>WASM + Rust</h1>
      <button id="greetButton">Greet</button>
      <button id="addButton">Add</button>
      <script src="main.js"></script>
    </body>
    </html>
    

    main.js

    javascript
    复制代码
    import * as wasm from './pkg/rust_wasm_example.js';
    
    document.getElementById('greetButton').addEventListener('click', () => {
      wasm.greet('Rust Developer');
    });
    
    document.getElementById('addButton').addEventListener('click', () => {
      alert(wasm.add(5, 7)); // Should alert 12
    });
    
  4. 设置 Webpack 构建: 创建一个 webpack.config.js 配置文件:

    js
    复制代码
    const path = require('path');
    
    module.exports = {
      entry: './index.js',
      output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
      },
      module: {
        rules: [
          {
            test: /.js$/,
            exclude: /node_modules/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env'],
              },
            },
          },
        ],
      },
    };
    
  5. 运行构建和启动服务器: 在命令行中运行以下命令:

    bash
    复制代码
    npx webpack --config webpack.config.js
    

    这将会构建你的项目并将所有文件打包到 dist/ 目录。

  6. 运行项目: 启动一个本地开发服务器(比如使用 http-server):

    bash
    复制代码
    npx http-server ./dist
    

    打开浏览器访问 http://localhost:8080,你应该可以看到两个按钮,“Add” 按钮会计算 5 + 7 的结果并弹出窗口,“Greet” 按钮会在浏览器的控制台输出 Hello, Rust Developer!

总结

通过以上步骤,你使用 Rust 编写代码,并将其编译为 WebAssembly(WASM)模块,然后通过 JavaScript 进行交互。这个过程的关键步骤包括:

  • 使用 wasm-pack 编译 Rust 代码为 WASM;
  • 使用 wasm-bindgen 库使得 Rust 代码与 JavaScript 进行互操作;
  • 使用 Webpack 等工具将 JavaScript 和 WASM 模块打包,并通过前端框架加载和交互。

这种组合利用了 Rust 的高性能和 WebAssembly 的跨平台特性,能够在浏览器中执行计算密集型任务。