双进程架构
灵动桌面框架基于 Tauri 2.x 的双进程模型,前端和后端在不同进程中运行,通过 IPC 通信。
架构图
┌─────────────────────────────────────────────────────┐
│ 应用窗口 │
│ ┌──────────────────┐ IPC ┌────────────────┐ │
│ │ WebView 进程 │ ←──────→ │ Rust Core 进程 │ │
│ │ │ invoke │ │ │
│ │ ● React 19 UI │ listen │ ● Commands │ │
│ │ ● Ant Design 6 │ emit │ ● Services │ │
│ │ ● TailwindCSS 4 │ │ ● Database │ │
│ │ ● Zustand 状态 │ │ ● 文件系统 │ │
│ │ ● React Router │ │ ● 系统 API │ │
│ └──────────────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────┘
WebView 进程(前端)
- 负责 UI 渲染和用户交互
- 使用操作系统自带的 WebView(Windows 为 WebView2、macOS 为 WKWebView、Linux 为 WebKitGTK),不随安装包打包浏览器内核,体积和内存占用都很低
- 技术栈:React 19 + TypeScript 5.8 + Ant Design 6
前端可以做的事:
- 渲染界面、响应用户操作
- 管理 UI 状态(Zustand)
- 调用后端 Command(通过
invoke) - 监听后端事件(通过
listen)
前端不应该做的事:
- 直接访问文件系统
- 直接调用外部 API(应通过 Rust 代理)
- 执行耗时计算(应委托给 Rust)
Rust Core 进程(后端)
- 负责 系统级操作和业务逻辑
- 原生 Rust 代码,性能极高
- 采用三层架构:Command → Service → Database
后端可以做的事:
- 数据库读写
- 文件系统操作
- 网络请求
- 系统级 API 调用
- 计算密集型任务
IPC 通信机制
invoke — 前端调用后端
// 前端调用(实际项目中应封装进 src/lib/api/,见 IPC 通信)
import { invoke } from '@tauri-apps/api/core'
const result = await invoke<string>('greet', { name: '灵动' })
// → "Hello, 灵动! 来自 Rust 的问候!"
// 后端处理(src-tauri/src/commands/system.rs)
#[tauri::command]
pub fn greet(name: &str) -> Result<String, CommandError> {
if name.is_empty() {
return Err(CommandError {
code: "INVALID_INPUT".to_string(),
message: "名称不能为空".to_string(),
});
}
Ok(format!("Hello, {}! 来自 Rust 的问候!", name))
}
emit / listen — 事件通信
// 后端发送事件(emit 来自 tauri::Emitter trait,需要先引入)
use tauri::Emitter;
app_handle.emit("download-progress", payload)?;
// 前端监听事件
import { listen } from '@tauri-apps/api/event'
listen('download-progress', (event) => {
console.log('进度:', event.payload)
})
数据流向
用户操作 → React 组件 → API 封装层 → invoke()
↓
Rust Command
↓
Service 层
↓
Database 层
↓
返回 Result
↓
React 组件 ← 更新 UI ← Promise resolve ←┘
为什么是双进程
- 安全隔离 — 前端无法直接访问系统资源,必须通过权限控制的 Command
- 性能 — Rust 后端处理重计算,前端保持流畅
- 稳定性 — 前端崩溃不影响后端数据安全