Appearance
Rust WebAssembly
WebAssembly(Wasm)是一种可移植的二进制格式,允许在浏览器中运行高性能代码。Rust 提供了强大的 WebAssembly 支持。本章节将介绍 Rust 与 WebAssembly 的集成。
环境设置
安装 wasm-pack
wasm-pack 是 Rust WebAssembly 项目的构建工具:
bash
cargo install wasm-pack安装 wasm-bindgen-cli
wasm-bindgen-cli 用于生成 Rust 和 JavaScript 之间的绑定:
bash
cargo install wasm-bindgen-cli创建 WebAssembly 项目
使用 wasm-pack 初始化项目
bash
wasm-pack new wasm-demo
cd wasm-demo项目结构
wasm-demo/
├── Cargo.toml
├── src/
│ ├── lib.rs
│ └── utils.rs
└── README.md编写 WebAssembly 代码
基本示例
rust
// src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}编译项目
bash
wasm-pack build --target web这将生成以下文件:
pkg/
├── wasm_demo_bg.wasm
├── wasm_demo.js
├── wasm_demo.d.ts
└── package.json在网页中使用
创建 HTML 文件
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Rust WebAssembly Demo</title>
</head>
<body>
<h1>Rust WebAssembly Demo</h1>
<button id="greet">Greet</button>
<button id="add">Add</button>
<div id="result"></div>
<script type="module">
import init, { greet, add } from './pkg/wasm_demo.js';
async function run() {
await init();
document.getElementById('greet').addEventListener('click', () => {
greet('World');
});
document.getElementById('add').addEventListener('click', () => {
const result = add(5, 3);
document.getElementById('result').textContent = `5 + 3 = ${result}`;
});
}
run();
</script>
</body>
</html>运行项目
使用本地服务器运行项目:
bash
python -m http.server然后在浏览器中访问 http://localhost:8000。
与 JavaScript 交互
从 Rust 调用 JavaScript
rust
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
// 调用 console.log
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
// 调用 DOM API
#[wasm_bindgen(js_namespace = document)]
fn getElementById(id: &str) -> Option<Element>;
#[wasm_bindgen]
type Element;
#[wasm_bindgen(method)]
fn innerHTML(this: &Element) -> String;
#[wasm_bindgen(method)]
fn set_innerHTML(this: &Element, value: &str);
}
#[wasm_bindgen]
pub fn update_element(id: &str, content: &str) {
if let Some(element) = getElementById(id) {
element.set_innerHTML(content);
log(&format!("Updated element {} with content: {}", id, content));
}
}从 JavaScript 调用 Rust
rust
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Counter {
count: i32,
}
#[wasm_bindgen]
impl Counter {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Counter { count: 0 }
}
pub fn increment(&mut self) {
self.count += 1;
}
pub fn decrement(&mut self) {
self.count -= 1;
}
pub fn get_count(&self) -> i32 {
self.count
}
}JavaScript 代码:
javascript
import init, { Counter } from './pkg/wasm_demo.js';
async function run() {
await init();
const counter = new Counter();
console.log('Initial count:', counter.get_count()); // 0
counter.increment();
console.log('After increment:', counter.get_count()); // 1
counter.decrement();
console.log('After decrement:', counter.get_count()); // 0
}
run();性能优化
使用 wee_alloc 减少 Wasm 体积
在 Cargo.toml 中添加:
toml
[dependencies]
wasm-bindgen = "0.2"
wee_alloc = "0.4"
[profile.release]
opt-level = "s"在 lib.rs 中使用:
rust
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;开启优化
bash
wasm-pack build --target web --release总结
- WebAssembly:一种可移植的二进制格式
- wasm-pack:Rust WebAssembly 项目的构建工具
- wasm-bindgen:生成 Rust 和 JavaScript 之间的绑定
- 从 Rust 调用 JavaScript:使用
extern "C"块 - 从 JavaScript 调用 Rust:使用
#[wasm_bindgen]宏 - 性能优化:使用
wee_alloc和开启优化
Rust 与 WebAssembly 的集成使得我们可以在浏览器中运行高性能的 Rust 代码,为 Web 应用带来更好的性能体验。通过本章节的学习,你应该已经掌握了 Rust 与 WebAssembly 集成的基本方法。