Tauri 架构设计
Tauri 是一个用 Rust 构建轻量、安全的跨平台桌面/移动应用框架,前端使用系统原生 WebView 而非捆绑 Chromium。
🏗️ 整体架构
┌─────────────────────────────────────────────────┐
│ Frontend │
│ (HTML/CSS/JS - Any Framework) │
│ React / Vue / Svelte │
└──────────────────┬──────────────────────────────┘
│ invoke() / Events
│ (IPC Message Passing)
┌──────────────────▼──────────────────────────────┐
│ Tauri Core (Rust) │
│ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ Commands │ │ Events │ │ State Mgmt │ │
│ └──────────┘ └──────────┘ └───────────────┘ │
│ ┌──────────────────────────────────────────────┐│
│ │ Plugin System ││
│ │ fs / shell / dialog / notification / ... ││
│ └──────────────────────────────────────────────┘│
└──────────────────┬──────────────────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌───────┐ ┌─────────┐ ┌──────────┐
│ TAO │ │ WRY │ │ Bundler │
│Window │ │WebView │ │ 打包发布 │
│ Mgmt │ │Rendering│ │ │
└───┬───┘ └────┬────┘ └──────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────┐
│ Operating System │
│ Windows(WebView2) macOS(WKWebView) Linux(GTK) │
│ Android(System WebView) iOS(WKWebView) │
└─────────────────────────────────────────────────┘
🔑 核心设计思想
1. 系统 WebView 而非捆绑浏览器
这是 Tauri 与 Electron 最根本的架构差异:
| 方案 | 做法 | 代价 |
|---|---|---|
| Electron | 捆绑 Chromium + Node.js | 每个应用 100-200MB |
| Tauri | 使用系统已有的 WebView | 应用仅 3-10MB |
设计哲学:用户的操作系统已经内置了浏览器引擎(Windows 有 WebView2/Edge,macOS 有 WKWebView/Safari,Linux 有 WebKitGTK),没必要每个应用再带一份。
权衡:跨平台渲染一致性不如 Electron(不同系统的 WebView 实现有差异),但换来了极小的体积和极低的内存占用。
2. Rust 作为后端语言
选择 Rust 的原因:
- 内存安全:编译期保证无数据竞争,减少安全漏洞
- 零运行时开销:不需要 GC,二进制体积小
- 系统级能力:可以直接调用 OS API,性能接近原生
- 反编译困难:保护应用逻辑不被轻易逆向
对比 Electron 的 Node.js 后端:
- Node.js 有 GC 停顿,内存占用高
- JavaScript 源码容易被查看和修改
- Node.js 的系统级能力受限
3. 安全优先的 IPC 模型
Tauri v2 引入了 Capability-based Permission System(基于能力的权限系统):
Frontend (不可信)
│
│ invoke("read_file", { path: "/tmp/test.txt" })
│
▼
┌─────────────────────────────────────┐
│ Runtime Authority │
│ 检查: │
│ 1. 该窗口是否有此 Capability? │
│ 2. 该权限是否在 allow 列表中? │
│ 3. 路径是否在 Scope 范围内? │
└──────────────┬──────────────────────┘
│ 通过 → 执行 Rust Command
│ 拒绝 → 返回 Permission Denied
▼
Rust Backend (完全信任)
核心概念:
- Permission:定义单个操作是否允许(如
fs:allow-read-text-file) - Capability:将多个 Permission 分组,绑定到特定窗口
- Scope:细粒度限制(如只允许读取
$HOME/test.txt) - Runtime Authority:运行时权限检查器
4. 进程隔离模型
┌─────────────────────┐
│ Main Process │ ← Rust 代码,完全信任
│ (Core Process) │ ← 管理窗口、系统托盘、生命周期
└──────────┬──────────┘
│ IPC (消息传递)
┌──────────▼──────────┐
│ WebView Process │ ← 前端代码,受限沙箱
│ (Renderer Process) │ ← 只能通过 invoke() 调用后端
└─────────────────────┘
前端代码运行在 WebView 的沙箱中,不能直接访问文件系统、网络、系统 API。所有系统交互必须通过 IPC 调用 Rust 后端,后端再通过权限系统验证。
🧩 核心组件
TAO — 窗口管理
- 负责创建和管理应用窗口
- 处理窗口事件(大小、位置、焦点)
- 管理系统托盘(Tray Icon)
- 处理全局快捷键
- 跨平台抽象:macOS/Windows/Linux/Android/iOS
WRY — WebView 渲染
- 统一接口封装各平台 WebView
- Windows → WebView2(基于 Edge/Chromium)
- macOS/iOS → WKWebView(基于 Safari/WebKit)
- Linux → WebKitGTK
- Android → Android System WebView
- 处理 JS ↔ Rust 的消息传递
Bundler — 打包发布
- 生成各平台安装包:
.app/.dmg(macOS)、.msi/.exe(Windows)、.deb/.rpm/.AppImage(Linux) - 自动签名和公证
- 支持 NSIS 安装程序
Plugin System — 插件系统
Tauri v2 的插件系统支持:
- Rust 端:定义 Commands、管理 State、注册事件监听
- JS 端:提供 TypeScript API 给前端调用
- 移动端:通过 Swift/Kotlin 绑定调用原生 API
官方维护的插件:
tauri-plugin-fs— 文件系统操作tauri-plugin-shell— Shell 命令执行tauri-plugin-dialog— 文件选择/消息对话框tauri-plugin-notification— 系统通知tauri-plugin-sql— SQL 数据库访问(sqlx)tauri-plugin-store— 持久化键值存储tauri-plugin-stronghold— 加密安全数据库tauri-plugin-updater— 应用内更新tauri-plugin-websocket— WebSocket 客户端tauri-plugin-clipboard— 剪贴板操作tauri-plugin-global-shortcut— 全局快捷键tauri-plugin-autostart— 开机自启tauri-plugin-nfc— NFC(移动端)tauri-plugin-biometric— 生物识别(移动端)tauri-plugin-barcode-scanner— 二维码扫描(移动端)
🔄 IPC 通信机制
Commands(命令调用)
前端通过 invoke() 调用 Rust 函数,这是最主要的通信方式:
// Rust 端定义
#[tauri::command]
fn greet(name: String) -> String {
format!("Hello, {}!", name)
}
// 注册
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
// JS 端调用
import { invoke } from '@tauri-apps/api/core';
const result = await invoke('greet', { name: 'World' });
特点:
- 请求-响应模式(Promise)
- 支持异步命令(async fn)
- 自动序列化/反序列化(serde)
- 错误通过
Result<T, E>传递
Events(事件系统)
双向事件通信,适合实时通知和流式数据:
// Rust → Frontend
app.emit("download-progress", serde_json::json!({
"percent": 75,
"file": "data.zip"
}))?;
// Frontend 监听
import { listen } from '@tauri-apps/api/event';
const unlisten = await listen('download-progress', (event) => {
console.log(event.payload.percent); // 75
});
// 清理
unlisten();
State Management(状态管理)
Rust 端的全局状态管理:
pub struct AppState {
pub db: Mutex<Database>,
pub config: Mutex<Config>,
}
tauri::Builder::default()
.manage(AppState { ... })
#[tauri::command]
fn get_config(state: tauri::State<AppState>) -> Config {
state.config.lock().unwrap().clone()
}
📐 进程模型
Tauri 应用运行时包含以下进程:
-
主进程(Main/Core Process)
- Rust 编译的原生二进制
- 管理应用生命周期
- 处理所有系统交互
- 运行 Commands、管理 State
-
WebView 进程
- 每个窗口一个 WebView 实例
- 运行前端 HTML/CSS/JS
- 受沙箱限制,只能通过 IPC 与主进程通信
-
多窗口支持(v2)
- 每个窗口可以有不同的权限(Capability)
- 窗口间可以互相通信(通过事件系统)
🆚 与 Electron 架构对比
| 维度 | Tauri | Electron |
|---|---|---|
| 渲染引擎 | 系统 WebView | 捆绑 Chromium |
| 后端语言 | Rust | Node.js |
| 进程模型 | 主进程 + WebView 进程 | 主进程 + Renderer 进程 |
| IPC 机制 | invoke() + Events | ipcMain/ipcRenderer |
| 安全模型 | Capability-based(默认安全) | 需手动配置(默认开放) |
| 二进制体积 | 3-10MB | 100-200MB |
| 内存占用 | 30-50MB | 150-300MB |
| 启动速度 | 0.3-1s | 1-3s |
| 移动端支持 | iOS + Android(v2) | 无 |
| 渲染一致性 | 跨平台有差异 | 完全一致 |
| 构建速度 | 慢(Rust 编译) | 快(JS 工具链) |
🛡️ 安全架构
Tauri 的安全设计遵循 最小权限原则:
- 默认无权限:前端代码默认不能访问任何系统资源
- 声明式授权:通过 Capability 文件显式声明需要的权限
- 作用域限制:权限可以进一步限制到具体路径/URL
- 运行时检查:每次 IPC 调用都经过 Runtime Authority 验证
- 安全审计:每个大版本都经过独立安全审计
🔗 相关链接
📝 个人备注
(留白,供后续补充学习心得)