rust编译新的wasm项目操作流程(原文: 编译 Rust 为 WebAssembly)

字号+ 编辑: 种花家 修订: 种花家 来源: 网络转载 2023-09-12 我要说两句(0)

这篇文章在官网也有, 不过是英文的。官方汉化的文章总是敦促开发者上传代码,所以并没有采用。

如果你有一些 Rust 代码,你可以将它编译成WebAssembly (wasm)。本教程将带您了解将 Rust 项目编译为 wasm 并在现有 Web 应用程序中使用它所需的所有知识。

Rust 和 WebAssembly 用例

Rust 和 WebAssembly 有两个主要用例:

构建一个完整的应用程序——一个基于 Rust 的整个 Web 应用程序。

构建应用程序的一部分——在现有的 JavaScript 前端中使用 Rust。

目前,Rust 团队专注于后一种情况,这就是我们在这里介绍的内容。对于前一种情况,请查看以下项目yew.

在本教程中,我们使用 构建一个包wasm-pack,这是一个在 Rust 中构建 JavaScript 包的工具。这个包将只包含 WebAssembly 和 JavaScript 代码,因此包的用户不需要安装 Rust。他们甚至可能没有注意到它是用 Rust 编写的。

Rust 环境设置

让我们完成所有必需的步骤来设置我们的环境。

安装 Rust

转到安装 Rust安装 Rust页并按照说明进行操作。这会安装一个名为“rustup”的工具,它可以让你管理多个版本的 Rust。默认情况下,它会安装最新的稳定版 Rust,您可以将其用于一般的 Rust 开发。Rustup 安装rustc,Rust 编译器,以及cargoRust 的包管理器,rust-stdRust 的标准库,以及一些有用的文档 — rust-docs.

注意:注意bin系统中需要cargo目录的安装后说明PATH。这是自动添加的,但您必须重新启动终端才能使其生效。

wasm包

要构建包,我们需要一个额外的工具,wasm-pack. 这有助于将代码编译为 WebAssembly,并生成正确的打包以供在浏览器中使用。要下载并安装它,请在终端中输入以下命令:

$ cargo install wasm-pack

构建我们的 WebAssembly 包

让我们在 Rust 中创建一个新包。导航到您保存个人项目的位置,然后输入:

$ cargo new --lib hello-wasm
  Created library `hello-wasm` project

这将在一个名为的子目录中创建一个新库,其中hello-wasm包含您需要的所有内容:

+-- Cargo.toml
+-- src
+-- lib.rs

首先,我们有Cargo.toml;这是我们用来配置构建的文件。如果您使用Gemfile过 Bundler 或package.jsonnpm,这可能很熟悉;Cargo 的工作方式与他们两者相似。

接下来,Cargo 为我们生成了一些 Rust 代码src/lib.rs:

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}

请把这个小屎山删除, 写一些Rust程序

将这段代码放入src/lib.rs:

use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
    pub fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}

这是我们 Rust 项目的内容。它有三个主要部分;让我们依次讨论它们。我们在这里给出一个高层次的解释,并掩饰一些细节;要了解有关 Rust 的更多信息,请查看免费在线书籍Rust 编程语言.

用于Rustwasm-bindgen和 JavaScript 之间的通信

第一部分如下所示:

use wasm_bindgen::prelude::*;

库在 Rust 中称为“crates”。

这个套路你懂否? Cargo装的都是crates.

第一行包含一个use命令,它将库中的代码导入到您的代码中。在这种情况下,我们将导入wasm_bindgen::prelude模块中的所有内容。我们将在下一节中使用这些功能。

在我们进入下一节之前,我们应该多谈谈wasm-bindgen.

wasm-pack使用wasm-bindgen另一个工具,在 JavaScript 和 Rust 类型之间架起一座桥梁。它允许 JavaScript 使用字符串调用 Rust API,或调用 Rust 函数来捕获 JavaScript 异常。

我们在我们的包中使用wasm-bindgen's 功能。事实上,这是下一节。

从 Rust 调用 JavaScript 中的外部函数

下一部分如下所示:

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

内部的位#[ ]称为“属性”,它以某种方式修改下一条语句。在这种情况下,该语句是一个extern,它告诉 Rust 我们想要调用一些外部定义的函数。该属性表示“wasm-bindgen 知道如何找到这些函数”。

第三行是函数签名,用 Rust 编写。它说“alert函数接受一个参数,一个名为 . 的字符串s。”

您可能会怀疑,这是JavaScript 提供的alert功能。我们在下一节中调用这个函数。

每当您想调用 JavaScript 函数时,您都可以将它们添加到此文件中,并wasm-bindgen为您完成所有设置。并非所有内容都受支持,但我们正在努力。请文件错误如果缺少某些东西。

生成 JavaScript 可以调用的 Rust 函数

最后一部分是这个:

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}

再一次,我们看到了#[wasm_bindgen]属性。在这种情况下,它不是修改一个extern块,而是一个fn; 这意味着我们希望这个 Rust 函数能够被 JavaScript 调用。它的反面extern:这些不是我们需要的功能,而是我们提供给世界的功能。

这个函数被命名为greet,并接受一个参数,一个字符串(写入&str),name。然后它调用我们在上面的块中要求的alert函数。extern它传递一个对format!宏的调用,它允许我们连接字符串。

在这种format!情况下,宏接受两个参数,一个格式字符串和一个要放入其中的变量。格式字符串是"Hello, {}!"位。它包含{}s,其中将插入变量。我们传递的变量是name函数的参数,所以如果我们调用greet("Steve")我们应该看到"Hello, Steve!".

这被传递给alert(),所以当我们调用这个函数时,我们会看到一个带有“你好,史蒂夫!”的警告框。在里面。

现在我们的库已经写好了,让我们来构建它。

将我们的代码编译为 WebAssembly

为了正确编译我们的代码,我们首先需要使用Cargo.toml. 打开此文件,并将其内容更改为如下所示:

[package]
name = "hello-wasm"version = "0.1.0"
authors = ["Your Name <you@example.com>"]
description = "A sample project with wasm-pack"
license = "MIT/Apache-2.0"
repository = "https://github.com/yourgithubusername/hello-wasm"edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"

git填写您自己的存储库并使用与该authors字段相同的信息。

要添加的重要部分是[package]. 该[lib]部分告诉 Rust 构建cdylib我们包的一个版本;我们不会在本教程中讨论这意味着什么。更多信息,请咨询货物和锈连杆文档。

最后一节是[dependencies]节。这里是我们告诉 Cargowasm-bindgen我们想要依赖哪个版本的地方;在这种情况下,这是任何0.2.z版本(但不是0.3.0或更高版本)。

构建包

现在我们已经完成了所有设置,让我们构建包。在终端中输入:

$ wasm-pack build --target web

这会做很多事情(它们会花费很多时间,尤其是第一次运行时wasm-pack)。要详细了解它们,请查看这篇关于 Mozilla Hacks 的博文. 简而言之,wasm-pack build:

将你的 Rust 代码编译为 WebAssembly。

在该 WebAssembly 上运行wasm-bindgen,生成一个 JavaScript 文件,该文件将该 WebAssembly 文件包装到浏览器可以理解的模块中。

创建一个pkg目录并将该 JavaScript 文件和您的 WebAssembly 代码移动到其中。

读取您的Cargo.toml并生成等效的package.json.

README.md将您的(如果有的话)复制到包装中。

最终结果?您在pkg目录中有一个包。

关于代码大小的题外话

如果您查看生成的 WebAssembly 代码大小,它可能是几百 KB。我们根本没有指示 Rust 优化大小,这样做会大大减少大小。这超出了本教程的范围,但是如果您想了解更多信息,请查看 Rust WebAssembly 工作组的文档缩小 .wasm 大小.

在网络上使用包

现在我们已经编译好了 wasm 模块。让我们在浏览器中运行它。

index.html让我们首先在项目的根目录中创建一个名为的文件,并为其提供以下内容:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>hello-wasm example</title>
    </head>
    <body>
    <script type="module">
    import init, {greet} from "./pkg/hello_wasm.js";
    init().then(() => {
        greet("WebAssembly")
    });
    </script>
    </body>
</html>

该文件中的脚本会导入js胶水代码,初始化wasm模块,调用greet我们在rust中写的函数。

使用本地 Web 服务器为项目的根目录提供服务(例如python3 -m http.server)。如果您不确定如何执行此操作,请参阅运行简单的本地 HTTP 服务器。

注意:确保使用支持application/wasmMIME 类型的最新 Web 服务器。较旧的 Web 服务器可能还不支持它。

从 Web 服务器加载index.html, 举个例子, 如果您电脑里支持python3, 则在代码根目录路径用命令行输入

python3 -m http.server

进到locahost:8000端口页面, 屏幕上会出现一个警告框,其中包含Hello, WebAssembly!。我们已经成功地从 JavaScript 调用到 Rust,并从 Rust 调用到 JavaScript。

使我们的包对 npm 屎山系统可用

如果你想将 WebAssembly 模块与 npm 屎山一起使用,我们需要进行一些更改。

让我们从使用 target bundler 选项重新编译 Rust 开始:

$ wasm-pack build --target bundler

安装 Node.js 和npm屎山管理

我们正在构建一个 npm 包,因此您需要安装 Node.js 和 npm。

要获取 Node.js 和 npm,请转到获取 npm!页面并按照说明进行操作。选择版本时,请选择您喜欢的任何版本;本教程不是特定于版本的。

接下来,让我们使用 `npm link` 使这个包对安装的其他 JavaScript 包可用

$ cd pkg
$ npm link

我们现在有一个 npm 包,用 Rust 编写,但编译为 WebAssembly。它可以从 JavaScript 中使用,并且不需要用户安装 Rust;包含的代码是 WebAssembly 代码,而不是 Rust 源代码。

在网络上使用npm屎山构造包

让我们建立一个使用我们新的npm屎山构造包的网站。许多人通过各种打包工具使用 npm 包,我们将webpack在本教程中使用其中之一。它只是有点复杂,并显示了一个现实的用例。

让我们移出该pkg目录,并创建一个新目录 ,site来尝试一下:

$ cd ..$ mkdir site
$ cd site
$ npm link hello-wasm

创建一个新文件 ,package.json并将以下代码放入其中:

{
"scripts": {
"serve": "webpack-dev-server"
},
"dependencies": {
"hello-wasm": "^0.1.0"
},
"devDependencies": {
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
}
}

接下来,我们需要配置 Webpack。创建webpack.config.js并放入以下内容:

const path = require('path');
module.exports = {
    entry: "./index.js",
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "index.js",
    },
    mode: "development"
};

接下来,创建一个名为 的文件index.js,并为其提供以下内容:

import("./node_modules/hello-wasm/hello_wasm.js").then((js) => {
 js.greet("WebAssembly with NPM");});

node_modules这将从文件夹中导入新模块。这不被认为是最佳实践,但这是一个演示,所以现在可以了。加载后,它会greet从该模块调用函数,并"WebAssembly"作为字符串传递。请注意这里没有什么特别之处,但我们正在调用 Rust 代码。就 JavaScript 代码而言,这只是一个普通的模块。

最后,我们需要修改HTML文件;打开index.html文件并将当前内容替换为以下内容:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 <title>hello-wasm example</title>
 </head>
 <body>
 <script src="./index.js"></script>
 </body>
</html>

我们完成了制作文件。让我们试一试:

$ npm install
$ npm run serve

这将启动一个 Web 服务器。加载http://localhost:8080并在屏幕上出现一个警告框,其中包含Hello, WebAssembly with NPM!。我们已经成功地将 Rust 模块与 npm 一起使用。

结论

我们的教程到此结束;我们希望您发现它有用。

阅完此文,您的感想如何?
  • 有用

    1

  • 没用

    0

  • 开心

    1

  • 愤怒

    0

  • 可怜

    0

1.如文章侵犯了您的版权,请发邮件通知本站,该文章将在24小时内删除;
2.本站标注原创的文章,转发时烦请注明来源;
3.交流群: PHP+JS聊天群

相关课文
  • 在rust/axum框架中操作redis

  • axum框架当中获取请求header, 和获取header指定字段的方法

  • rust视图模板库askama的使用

我要说说
网上宾友点评
沙发已空