Rust Web 全棧開發(十一):WebAssembly 嘗鮮

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 輸出電流…