目录
1. Tauri:Rust 驱动的桌面应用
1.1 为什么替代 Electron
| 维度 | Electron | Tauri |
|---|---|---|
| 后端运行时 | Node.js + Chromium | Rust + 系统 WebView |
| 打包体积 | ~150MB | ~3MB |
| 内存占用 | 高(完整 Chromium) | 低(共享系统 WebView) |
| 安全性 | 中等 | 高(Rust 内存安全 + 进程隔离) |
| 前端框架 | 任意 | 任意(React/Vue/Svelte/纯 HTML) |
1.2 项目结构
my-tauri-app/
├── src/ # 前端代码(任意框架)
├── src-tauri/ # Rust 后端
│ ├── src/main.rs
│ ├── Cargo.toml
│ └── tauri.conf.json
1.3 核心概念:Commands
// src-tauri/src/main.rs
use tauri::command;
#[command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust.", name)
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
前端调用:
import { invoke } from '@tauri-apps/api/tauri';
const response = await invoke('greet', { name: 'World' });
console.log(response); // "Hello, World! You've been greeted from Rust."
1.4 状态管理
use tauri::{State, Manager};
use std::sync::Mutex;
struct AppState {
counter: Mutex<i32>,
}
#[command]
fn increment_counter(state: State<AppState>) -> i32 {
let mut counter = state.counter.lock().unwrap();
*counter += 1;
*counter
}
fn main() {
tauri::Builder::default()
.manage(AppState { counter: Mutex::new(0) })
.invoke_handler(tauri::generate_handler![increment_counter])
.run(tauri::generate_context!())
.unwrap();
}
1.5 文件系统访问
use tauri::api::path::document_dir;
use std::fs;
#[command]
fn save_file(filename: String, content: String) -> Result<(), String> {
let path = document_dir()
.ok_or("无法获取文档目录")?
.join(filename);
fs::write(path, content).map_err(|e| e.to_string())
}
1.6 窗口管理
use tauri::{WindowBuilder, WindowUrl};
fn create_settings_window(app: &tauri::AppHandle) {
WindowBuilder::new(
app,
"settings",
WindowUrl::App("settings.html".into())
)
.title("Settings")
.inner_size(600.0, 400.0)
.build()
.unwrap();
}
2. Tauri 2.0 与移动端支持
Tauri 2.0 新增了 iOS 和 Android 支持,使用系统 WebView(WKWebView / WebView):
cargo install tauri-cli@^2.0
cargo tauri android init
cargo tauri android dev
移动端特有的 API:
#[command]
async fn scan_qr_code() -> Result<String, String> {
// 调用移动端原生扫码能力
tauri_barcode_scanner::scan()
.await
.map_err(|e| e.to_string())
}
3. WebAssembly 编译与交互
3.1 为什么用 Rust 编译 WASM
- 无需 GC:WASM 目前没有 GC,Rust 的所有权模型完美契合
- 体积优化:wasm-opt 可进一步压缩,低至几 KB
- 性能接近原生:Wasmtime/Wasmer 运行时 JIT 编译
3.2 wasm-bindgen:Rust ↔ JS 桥梁
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[wasm_bindgen]
pub struct Point {
x: f64,
y: f64,
}
#[wasm_bindgen]
impl Point {
#[wasm_bindgen(constructor)]
pub fn new(x: f64, y: f64) -> Point {
Point { x, y }
}
pub fn distance(&self, other: &Point) -> f64 {
((self.x - other.x).powi(2) + (self.y - other.y).powi(2)).sqrt()
}
}
JavaScript 调用:
import init, { add, Point } from './pkg/my_wasm.js';
await init();
console.log(add(1, 2)); // 3
const p1 = new Point(0, 0);
const p2 = new Point(3, 4);
console.log(p1.distance(p2)); // 5
3.3 wasm-pack 工作流
# 安装
cargo install wasm-pack
# 编译为浏览器适用的 WASM
wasm-pack build --target web
# 编译为 Node.js 模块
wasm-pack build --target nodejs
# 编译为 bundler(webpack/rollup/vite)
wasm-pack build --target bundler
3.4 web-sys 与浏览器 API
use wasm_bindgen::JsCast;
use web_sys::{HtmlCanvasElement, CanvasRenderingContext2d};
#[wasm_bindgen]
pub fn draw_circle(canvas_id: &str, x: f64, y: f64, r: f64) {
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document.get_element_by_id(canvas_id)
.unwrap()
.dyn_into::<HtmlCanvasElement>()
.unwrap();
let context = canvas.get_context("2d")
.unwrap()
.unwrap()
.dyn_into::<CanvasRenderingContext2d>()
.unwrap();
context.begin_path();
context.arc(x, y, r, 0.0, std::f64::consts::PI * 2.0)
.unwrap();
context.stroke();
}
3.5 wee_alloc:缩小 WASM 体积
// 使用更小的分配器(适合 < 32KB 的场景)
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
4. WASI:WASM 系统接口
WASI(WebAssembly System Interface)让 WASM 在浏览器外运行,具有沙箱安全特性。
4.1 使用 Wasmtime 运行
use wasmtime::{Engine, Module, Store, Instance};
let engine = Engine::default();
let module = Module::from_file(&engine, "plugin.wasm")?;
let mut store = Store::new(&engine, ());
let instance = Instance::new(&mut store, &module, &[])?;
let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
run.call(&mut store, ())?;
4.2 Capability-based 安全
use wasmtime_wasi::{WasiCtx, WasiCtxBuilder};
let wasi = WasiCtxBuilder::new()
.inherit_stdio()
.preopened_dir("./data", "/data")? // 仅开放特定目录
.build();
4.3 插件化架构
// Host(宿主应用)
pub trait Plugin {
fn process(&self, input: &str) -> String;
}
// 编译为 WASM 的插件
#[no_mangle]
pub extern "C" fn process(input_ptr: i32, input_len: i32) -> i32 {
// ... 使用 WASI 内存交互
}
5. 嵌入式 Rust
5.1 no_std 环境
no_std 移除标准库,仅使用 core 和 alloc:
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use panic_halt as _;
#[entry]
fn main() -> ! {
let peripherals = stm32f4:: Peripherals::take().unwrap();
let gpioa = peripherals.GPIOA;
// 配置引脚...
loop {
// 主循环
}
}
5.2 embedded-hal 抽象层
use embedded_hal::digital::OutputPin;
fn blink_led<T: OutputPin>(led: &mut T, delay_ms: u32) {
led.set_high().unwrap();
delay(delay_ms);
led.set_low().unwrap();
delay(delay_ms);
}
5.3 RTIC / Embassy 框架
| 框架 | 特点 |
|---|---|
| RTIC | 基于硬件任务调度,零成本抽象 |
| Embassy | 异步/await 嵌入式,类似 Tokio |
// Embassy 异步示例
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_stm32::init(Default::default());
let mut led = Output::new(p.PA5, Level::Low, Speed::Low);
loop {
led.set_high();
Timer::after(Duration::from_millis(300)).await;
led.set_low();
Timer::after(Duration::from_millis(300)).await;
}
}
5.4 Probe-rs 调试
# 无需 OpenOCD,纯 Rust 工具链
cargo install probe-rs --features cli
# 烧录
cargo embed --release
# 调试
cargo run --bin my_app
6. 跨平台发布策略
6.1 Cross 交叉编译
cargo install cross
# Linux → Windows
cross build --target x86_64-pc-windows-gnu
# Linux → macOS
cross build --target x86_64-apple-darwin
# Linux → ARM64
cross build --target aarch64-unknown-linux-gnu
6.2 cargo-dist
cargo install cargo-dist
# 配置 Cargo.toml
[workspace.metadata.dist]
targets = ["x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "aarch64-apple-darwin"]
# 生成所有平台的发布包
cargo dist build
6.3 平台特定代码
#[cfg(target_os = "windows")]
fn platform_init() { /* Windows 特定初始化 */ }
#[cfg(target_os = "macos")]
fn platform_init() { /* macOS 特定初始化 */ }
#[cfg(target_os = "linux")]
fn platform_init() { /* Linux 特定初始化 */ }
7. 总结与选型
| 场景 | 技术方案 | 生态成熟度 |
|---|---|---|
| 跨平台桌面 App | Tauri 2.0 | ⭐⭐⭐⭐⭐ |
| 浏览器内高性能计算 | WASM + wasm-bindgen | ⭐⭐⭐⭐⭐ |
| 插件/脚本系统 | WASI + Wasmtime | ⭐⭐⭐⭐ |
| 裸机 MCU | Embassy + embedded-hal | ⭐⭐⭐⭐ |
| 浏览器游戏引擎 | WASM + wgpu/WebGPU | ⭐⭐⭐⭐ |
Rust 在跨平台领域的优势在于一份代码,多处编译:Tauri 的前后端共享类型定义(通过 TypeScript 生成),WASM 的严格沙箱安全保障,嵌入式领域的零成本抽象——这些都是其他语言难以同时满足的。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。
「rust」更多文章
Rust 错误处理与测试:thiserror、mockall 与属性测试
Rust 错误处理最佳实践:Result/Option 组合子、thiserror 与 anyhow 选型、panic 边界控制、单元/集成/文档测试、mockall 模拟、property-based testing 与代码覆盖率。
Rust 系统编程与性能优化:零拷贝、内存剖析与编译调优
Rust 系统编程深度实践:操作系统原语、零拷贝 I/O、mmap 内存映射、性能剖析(cargo flamegraph)、编译器优化(LTO/PGO)、Benchmark 与内存分析,以及 no_std 嵌入式场景。
Rust 核心概念详解:所有权、Trait 与宏系统
Rust 核心概念全景解析:所有权模型、借用检查器、生命周期、Trait 系统、泛型编程、声明宏与过程宏,以及 Cargo 工作区与 crates 生态体系。