跳到正文
灵动桌面框架
Esc
本栏目菜单

双进程架构

灵动桌面框架基于 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 ←┘

为什么是双进程

  1. 安全隔离 — 前端无法直接访问系统资源,必须通过权限控制的 Command
  2. 性能 — Rust 后端处理重计算,前端保持流畅
  3. 稳定性 — 前端崩溃不影响后端数据安全