Rust Web 全栈开发(十一):WebAssembly 尝鲜

  • Rust Web 全栈开发(十一):WebAssembly 尝鲜
    • 什么是 WebAssembly?
    • 安装 wasm-pack 和 cargo-generate
    • 使用项目模板
    • 构建项目
    • 生成网页
    • 安装依赖项
    • 在 www 中使用本地的 wasm-pack-template 包
    • 本地服务

Rust Web 全栈开发(十一):WebAssembly 尝鲜

参考视频:https://www.bilibili.com/video/BV1RP4y1G7KF

继续之前的 Actix 项目。

我们已经实现了一个 Web App,在网页端查看并操作数据库中教师的数据。现在我们想创建一个 WebAssembly App,查看并操作数据库中课程的数据。

在这里插入图片描述

什么是 WebAssembly?

WebAssembly 是一种新的编码方式,可以在现代浏览器中运行。

  • 它是一种低级的类汇编语言
  • 具有紧凑的二进制格式
  • 可以接近原生的性能运行
  • 并为 C/C++、C#、Rust 等语言提供一个编译目标,以便它们可以在 Web 上运行
  • 它也被设计为可以与 JavaScript 共存,允许两者一起工作

WebAssembly 不是汇编语言,它不针对特定的机器,而是中间编译器目标,针对浏览器。

在这里插入图片描述

WebAssembly 有两种格式:

  • 文本格式,后缀为 .wat
  • 二进制格式,后缀为 .wasm

WebAssembly 能做什么?

  • 可以把你编写 C/C++、C#、Rust 等语言的代码编译成 WebAssembly 模块
  • 你可以在 Web 应用中加载该模块,并通过 JavaScript 调用它
  • 它并不是为了替代 JS,而是与 JS 一起工作
  • 仍然需要 HTML 和 JS,因为 WebAssembly 无法访问平台 API,例如 DOM、WebGL …

在这里插入图片描述

一个 C 语言的例子:

在这里插入图片描述

  • 快速、高效、可移植:通过利用常见的硬件能力,WebAssembly 代码在不同平台上能够以接近本地速度
    运行。

  • 可读、可调试:WebAssembly 是一门低阶语言,但是它有确实有一种人类可读的文本格式(其标
    准最终版本目前仍在编制),这允许通过手工来写代码,看代码以及调试代码。

  • 保持安全:WebAssembly 被限制运行在一个安全的沙箱执行环境中。像其他网络代码一样,它遵循浏览器的同源策略和授权策略。

  • 不破坏网络:WebAssembly 的设计原则是与其他网络技术和谐共处并保持向后兼容。

安装 wasm-pack 和 cargo-generate

官方文档:https://rustwasm.github.io/docs/book/game-of-life/setup.html

  • wasm-pack 是构建、测试和发布 Rust 生成的 WebAssembly 的一站式商店。

  • cargo-generate 通过利用已有的 git 存储库作为模板,帮助你快速启动并运行新的 Rust 项目。

命令行执行以下两个命令:

cargo install wasm-pack
cargo install cargo-generate

使用项目模板

官方文档:https://rustwasm.github.io/docs/book/game-of-life/hello-world.html

项目模板预先配置了相同的默认值,因此你可以快速构建、集成和打包 Web 代码。

回到 Actix 项目的最顶层,在终端中用下面的命令克隆项目模板:

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

这里我一直 git 不下来:

在这里插入图片描述

就直接下载 zip,解压到 Actix 项目的最顶层了。

在这里插入图片描述

因为是手动添加的 wasm-pack-template,需要将其手动添加为 members:

在这里插入图片描述

先来看看 wasm-pack-template 的 Cargo.toml:

[package]
name = "{{project-name}}"
version = "0.1.0"
authors = ["{{authors}}"]
edition = "2018"[lib]
crate-type = ["cdylib", "rlib"][features]
default = ["console_error_panic_hook"][dependencies]
wasm-bindgen = "0.2.84"# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.7", optional = true }[dev-dependencies]
wasm-bindgen-test = "0.3.34"[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"

其中最核心的是依赖中的 wasm-bindgen,用于绑定生成器。

修改一下字段:

在这里插入图片描述

再来看 src 目录下的 lib.rs,这是我们要编译到 WebAssembly 的 Rust crate 的根文件。它使用 wasm-bindgen 与 JavaScript 进行交互。它导入 JavaScript 函数 alert,并导出 Rust 函数 greet,该函数会发出问候消息的警报。

mod utils;use wasm_bindgen::prelude::*;#[cfg(feature = "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-pack-template!");
}

在 Rust 中,想要调用前端的函数,需要这样声明:

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

Rust 函数想要被前端调用,需要加上 #[wasm_bindgen]。

在前端中,想要调用 Rust 的函数,需要这样声明:

#[wasm_bindgen]
pub fn greet() {alert("Hello, wasm-pack-template!");
}

将 alert 中的字符串改为 “Hello, wasm-pack-template!”。

utils.rs 模块提供了常用的实用程序,使 Rust 更容易编译到 WebAssembly。例如,在调试 wasm 代码时,这个文件很有用,但是我们现在可以忽略这个文件。

构建项目

我们使用 wasm-pack 编排以下构建步骤:

  • 确保我们有 Rust 1.30 或更新的版本,并且通过 Rust 安装了 wasm32-unknown-unknown 目标。

  • 通过 cargo 将 Rust 源代码编译成 WebAssembly .wasm 二进制文件。

  • 使用 wasm-bindgen 来生成 JavaScript API,以便使用 Rust 生成的 WebAssembly。

要完成所有这些,cd 到 wasm-pack-template 目录下,执行命令:

wasm-pack build

构建成功:

在这里插入图片描述

当构建完成后,我们可以在 pkg 目录中找到它的工件:

在这里插入图片描述

下面讲解几个重要的文件。

wasm-pack-template/pkg/wasm-pack-template_bg.wasm:由 Rust 编译器从 Rust 源代码生成的 WebAssembly 二进制文件。它包含所有 Rust 函数和数据的编译到 wasm 的版本。例如,它有一个导出的 greet 函数。

wasm-pack-template/pkg/wasm-pack-template.js:

import * as wasm from "./wasm_pack_template_bg.wasm";
export * from "./wasm_pack_template_bg.js";
import { __wbg_set_wasm } from "./wasm_pack_template_bg.js";
__wbg_set_wasm(wasm);
wasm.__wbindgen_start();

wasm-pack-template/pkg/wasm-pack-template.js 是包含 JavaScript 的胶水代码,由 wasm-bindgen 生成。它包含 JavaScript glue,用于将 DOM 和 JavaScript 函数导入 Rust,并将 WebAssembly 中的函数暴露给 JavaScript。

例如,有一个 JavaScript greet 函数,它包装了从 WebAssembly 模块导出的 greet 函数。现在,这种粘合并没有做太多的事情,但是当我们开始在 wasm 和 JavaScript 之间来回传递更多值时,它将帮助引导这些值跨越边界。

这里有问题,我把 wasm-pack-template/pkg/wasm-pack-template.js 改成了这样:

// import * as wasm from "./wasm_pack_template_bg.wasm";
import * as wasm from "./wasm_pack_template";
export * from "./wasm_pack_template_bg.js";
// import { __wbg_set_wasm } from "./wasm_pack_template_bg.js";
// __wbg_set_wasm(wasm);
// wasm.__wbindgen_start();
export function greet() {alert("Hello, wasm-pack-template!");
}

wasm-pack-template/pkg/wasm-pack-template.d.js:

/* tslint:disable */
/* eslint-disable */
export function greet(): void;

此类 .d.js 文件包含用于 JavaScript glue 的 TypeScript 类型声明。如果你使用 TypeScript,你可以检查调用 WebAssembly 函数的类型。如果你不使用 TypeScript,你可以安全地忽略这个文件。

wasm-pack-template/pkg/package.json:

{"name": "wasm-pack-template","type": "module","collaborators": ["xiye <812288728@qq.com>"],"version": "0.1.0","files": ["wasm_pack_template_bg.wasm","wasm_pack_template.js","wasm_pack_template_bg.js","wasm_pack_template.d.ts"],"main": "wasm_pack_template.js","types": "wasm_pack_template.d.ts","sideEffects": ["./wasm_pack_template.js","./snippets/*"]
}

package.json 文件包含生成的 JavaScript 和 WebAssembly 包的元数据。它被 npm 和 JavaScript 打包器用来确定包之间的依赖关系、包名、版本和其他一些东西。它帮助我们集成 JavaScript 工具,并允许我们将包发布到 npm。

生成网页

要获取 wasm-pack-template 包并在 Web 页面中使用它,我们需要使用 create-wasm-app 这个 JavaScript 项目模板。

首先下载 create-wasm-app 这个库:

npm install -g create-wasm-app

在 wasm-pack-template 目录下运行这个命令:

npm init wasm-app www

构建成功:

在这里插入图片描述

在 wasm-pack-template 目录下生成了一个 www 目录,与 pkg 目录并列:

在这里插入图片描述

让我们仔细看看其中的一些文件。

wasm-pack-template/www/package.json:

{"name": "create-wasm-app","version": "0.1.0","description": "create an app to consume rust-generated wasm packages","main": "index.js","bin": {"create-wasm-app": ".bin/create-wasm-app.js"},"scripts": {"build": "webpack --config webpack.config.js","start": "webpack-dev-server"},"repository": {"type": "git","url": "git+https://github.com/rustwasm/create-wasm-app.git"},"keywords": ["webassembly","wasm","rust","webpack"],"author": "Ashley Williams <ashley666ashley@gmail.com>","license": "(MIT OR Apache-2.0)","bugs": {"url": "https://github.com/rustwasm/create-wasm-app/issues"},"homepage": "https://github.com/rustwasm/create-wasm-app#readme","devDependencies": {"hello-wasm-pack": "^0.1.0","webpack": "^4.29.3","webpack-cli": "^3.1.0","webpack-dev-server": "^3.1.5","copy-webpack-plugin": "^5.0.0"}
}

这个 package.json 预先配置了 webpack 和 webpack-dev-server 依赖项,以及对 hello-wasm-pack 的依赖项,它是发布到 npm 的初始 wasm-pack-template 包的一个版本。

wasm-pack-template/www/webpack.config.js:

const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require('path');module.exports = {entry: "./bootstrap.js",output: {path: path.resolve(__dirname, "dist"),filename: "bootstrap.js",},mode: "development",plugins: [new CopyWebpackPlugin(['index.html'])],
};

该文件配置 webpack 及其本地开发服务器。它是预先配置的,你根本不需要调整它来让 webpack 和它的本地开发服务器工作。

wasm-pack-template/www/index.html:

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>Hello wasm-pack!</title></head><body><noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript><script src="./bootstrap.js"></script></body>
</html>

这是 Web 页面的根 HTML 文件。除了加载 bootstrap.js 之外,它没有做太多的事情,这是 index.js 的一个非常薄的包装。

wasm-pack-template/www/index.js:

import * as wasm from "hello-wasm-pack";wasm.greet();

这是 Web 页面 JavaScript 的主要入口点。它导入 hello-wasm-pack npm 包,其中包含默认的 wasm-pack-template 的编译 WebAssembly 和 JavaScript glue,然后调用 hello-wasm-pack 的 greet 函数。

安装依赖项

首先,通过在 wasm-pack-template/www 子目录下运行 npm install,确保本地开发服务器及其依赖已经安装:

在这里插入图片描述

这个命令只需要运行一次,就会安装 webpack JavaScript 打包器和它的开发服务器。

注意,使用 Rust 和 WebAssembly 并不需要 webpack,它只是我们为了方便而选择的打包器和开发服务器。Parcel 和 Rollup 还应该支持将 WebAssembly 作为 ECMAScript 模块导入。如果你愿意,你也可以使用 Rust 和 WebAssembly 而不使用捆绑器。

在 www 中使用本地的 wasm-pack-template 包

向 wasm-pack-template/www/package.json 中添加依赖:

  "dependencies": {"wasm-pack-template": "file:../pkg"},

修改 wasm-pack-template/www/index.js,不使用 hello-wasm-pack 中的 greet 函数,而使用我们的 greet 函数:

// import * as hello_wasm from "hello-wasm-pack";
import * as wasm from "wasm-pack-template";wasm.greet();

因为依赖有修改,需要再次在 wasm-pack-template/www 子目录下运行 npm install:

在这里插入图片描述

现在,我们的 Web 页面现在可以在本地访问了!

本地服务

接下来,为开发服务器打开一个新终端。在新终端中运行服务器可以让它在后台运行,并且不会阻止我们同时运行其他命令。在新的终端中,从 wasm-pack-template/www 目录中运行以下命令:

npm run start

构建成功:

在这里插入图片描述

将 Web 浏览器导航到 localhost:8081/,应该会看到一条警告消息:

在这里插入图片描述

任何时候进行更改并希望它们反映在 localhost:8081/ 上,只需在 wasm-pack-template 目录中重新运行 wasm-pack build 命令。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/91021.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/91021.shtml
英文地址,请注明出处:http://en.pswp.cn/web/91021.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Thymeleaf实战:SpringBoot用户管理系统

Thymeleaf 示例代码下面是完整代码示例&#xff0c;帮助理解 Thymeleaf 语法和后端代码的配合&#xff1a;1. 用户实体类 (User.java)/*** 用户实体类*/ public class User {private Long id; // 用户IDprivate String name; // 用户名private String email; /…

mysql查找数据库表中某几个连续的编号中中断的编号

在MySQL中查找表中连续编号中断的位置,可以通过以下几种方法实现: 基于范围的查询方法 通过自连接查询找出ID序列中的断点,例如查找1-100范围内缺失的ID: SELECT a.id + 1 AS start, MIN(b.id) - 1 AS end FROM

《剑指offer》-数据结构篇-树

题目重建二叉树树的子结构二叉树的镜像从上往下打印二叉树&#xff08;层序遍历&#xff09;把二叉树打印成多行按之字形顺序打印二叉树二叉搜索树的第k个结点&#xff08;中序遍历&#xff09;二叉搜索树的后序遍历序列&#xff08;后序遍历&#xff09;二叉树中和为某一值的路…

系统定时任务扩展开发指南

适用场景当系统内置定时任务类型无法满足业务需求时&#xff0c;开发者可通过本教程快速掌握自定义定时任务的扩展方法。本指南以"定时检测服务"为例&#xff0c;演示完整开发流程。我想添加一个定时任务 ,而这里没有我需要的,我怎么来添加比如我想添加一个定时检测用…

R语言简介(附电子书资料)

概述 R语言是一种专为统计计算和数据分析设计的编程语言&#xff0c;自诞生以来&#xff0c;凭借其强大的统计分析能力和丰富的可视化功能&#xff0c;成为数据科学、统计学、机器学习等领域的重要工具。电子书资料&#xff1a;https://pan.quark.cn/s/23050825f2be 一、核心特…

关于前端的性能优化

性能优化主要涵盖了以下四个方面: (tip:仅代表个人总结,如有不当,还希望看到的大佬多多指示) 减少网络请求:合并文件、使用 CDN、启用缓存。 优化资源加载:代码分割、懒加载、图片压缩。 提升渲染性能:减少重绘回流、防抖节流、使用 Web Worker。 监控和迭代:定期使用工…

用 FFmpeg 把视频输出为图片序列

用 FFmpeg 把视频输出为图片序列 【推荐】输出为PNG图片序列&#xff08;无损&#xff09; mkdir "D:\Downloads\Recording" ffmpeg -i "C:\Users\33589\Videos\1.mp4" "D:\Downloads\Recording\Recording_%05d.png" 参数含义-i输入视频路径&am…

【linux】高可用集群Keepalived

Keepalived简介Keepalived 是一个基于 VRRP&#xff08;虚拟路由冗余协议&#xff09;的高可用解决方案&#xff0c;主要用于实现 Linux 服务器的负载均衡和故障转移。它通过检测服务器状态并自动切换服务&#xff0c;确保系统在单点故障时仍能保持可用性Keeplived安装启用及配…

如何检查服务器数据盘是否挂载成功?

在服务器配置过程中&#xff0c;确保数据盘正确挂载是非常重要的。如果数据盘未挂载成功&#xff0c;您可能无法访问数据盘上的存储空间。以下是检查Linux服务器中数据盘是否挂载成功的详细步骤&#xff0c;以及如何解决挂载问题。1. 检查数据盘是否挂载成功1.1 使用 df -h 查看…

机器学习概述与 KNN 算法详解

机器学习概述与 KNN 算法详解引言在当今数字化时代&#xff0c;机器学习作为人工智能的核心技术&#xff0c;正深刻改变着我们的生活与工作方式。从日常的智能推荐到复杂的医疗诊断&#xff0c;机器学习技术的应用无处不在。本文将从机器学习的基本概念出发&#xff0c;阐述其核…

Java EE前端技术编程脚本语言JavaScript

-CoderOilStation(程序员编程助手科技股份责任有限公司)Java EE前端技术编程脚本语言JavaScript低代码编程技术编写少量的代码规则。JavaScript脚本编程语言具体细节配置方式编程。前端技术过渡web3.0企业数字化。Java Service Page (JSP) JavaEE jdk6.5 发布企业应用版本Java研…

Docker+Kubernetes 实战:数据模型的弹性伸缩与高可用部署方案

在生产环境中,数据模型的部署面临双重挑战:一方面要应对流量波动(如电商大促期间预测接口调用量激增 10 倍),另一方面需保证服务零中断(金融风控模型 downtime 每增加 1 分钟可能导致数十万元损失)。 本文基于实际项目经验,详细讲解如何通过 Docker 容器化与 Kubernet…

vue3【组件封装】头像裁剪 S-avatar.vue

最终效果 技术要点 图片裁剪 安装依赖 vue-cropper npm install vue-croppernext专用于vue3 项目的图片裁剪&#xff0c;详细使用参考官方文档 页面使用 import "vue-cropper/dist/index.css"; import { VueCropper } from "vue-cropper";<vue-crop…

铜金矿数据分组优化系统设计与实现

铜金矿数据分组优化系统设计与实现 1. 项目概述 本项目旨在开发一个Python程序,用于根据给定的四组分组规则,优化包含金吨、干吨和铜单价等信息的Excel数据分组,以最大化总金额。系统需要处理的核心计算是每条数据的铜货值,其公式为:结算铜金吨 铜单价 (价格系数 + 奖…

Python动态规划:从基础到高阶优化的全面指南(3)

七、动态规划性能优化实战7.1 矩阵快速幂优化def matrix_mult(A, B):"""矩阵乘法"""n len(A)m len(B[0])p len(B)C [[0]*m for _ in range(n)]for i in range(n):for k in range(p):if A[i][k]:for j in range(m):C[i][j] A[i][k] * B[k][j…

海外红人营销的下一站:APP出海如何布局虚拟网红与UGC生态?

在全球移动互联网竞争日益激烈的今天&#xff0c;APP出海推广的重心正从传统流量采买和真人KOL合作&#xff0c;逐步向更具未来感的方向演进。虚拟网红、AI生成内容以及用户生成内容的融合&#xff0c;正为海外红人营销注入全新活力。这不仅是技术革新&#xff0c;更是用户行为…

CentOS网卡未被托管解决记录

VMWare挂起关机&#xff0c;又重启后&#xff0c;出现一些很奇怪的问题。 我的几台CentOS的网卡都不见了&#xff0c;显示网卡未被托管 [rootlocalhost ~]# nmcli device status DEVICE TYPE STATE CONNECTION virbr0 bridge 未托管 -- ens33 …

Node.js 中的内置模板path

1. path的作用&#xff1a;path 是 Node.js 中的一个内置模块&#xff0c;用于处理文件和目录路径。它提供了一些工具来处理路径字符串&#xff0c;确保路径操作跨平台兼容&#xff08;Windows 和 Unix 风格的路径分隔符&#xff09;2.path的常用方法path.join()和数组的join方…

重生之我在暑假学习微服务第三天《Docker-上篇》

个人主页&#xff1a;VON文章所属专栏&#xff1a;微服务系列文章链接&#xff1a;重生之我在暑假学习微服务第一天《MybatisPlus-上篇》-CSDN博客重生之我在暑假学习微服务第二天《MybatisPlus-下篇》-CSDN博客时间&#xff1a;每天12点前准时更新 特别声明&#xff1a;本篇文…

【硬件】LT3763中文手册

目录 1.简介 1.1 特点 1.2 简述 1.3 典型原理图 1.4 绝对最大额定值 2.电气特性 3.引脚功能 4.框图 4.1 设计电感电流 4.2 电感选择 4.3 开关MOSFET选择 4.4 输入电容选择 4.5 输出电容选择 4.6 CBOOST电容选择 4.7 INTVCC电容器选择 4.8 Soft-Start 4.9 输出电流…