第十章 Tauri 架构全景#

"要驾驭一个框架,先要看透它的骨架。"

经过 Part 1 的 Rust 速成,你已经具备了阅读和编写 Rust 代码的能力。从本章开始,我们正式进入 Tauri 的世界。本章将从宏观视角剖析 Tauri 的架构设计,理解它为什么能做到"小而安全"。

        mindmap
  root((Tauri 架构全景))
    双进程
      Core Process
      WebView Process
      IPC Bridge
    与 Electron 对比
      不内嵌 Chromium
      Rust 替代 Node
      更小攻击面
    安全模型
      最小权限
      capabilities
      CSP
    Hive 基础
      命令
      事件
      状态
    

10.1 Tauri 与 Electron:架构对比#

在深入 Tauri 之前,我们先对比它与 Electron 的架构差异:

┌─────────────────────────────────────────────────────┐
│                    Electron                          │
│                                                     │
│  ┌─────────────┐    ┌─────────────────────────────┐ │
│  │ Main Process│    │    Renderer Process          │ │
│  │  (Node.js)  │◄──►│  (Chromium 完整内核)         │ │
│  │             │IPC │  HTML / CSS / JS             │ │
│  └─────────────┘    └─────────────────────────────┘ │
│                                                     │
│  打包体积:~150 MB+(含完整 Chromium + Node.js)      │
│  内存占用:~100-300 MB                               │
└─────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────┐
│                     Tauri                            │
│                                                     │
│  ┌─────────────┐    ┌─────────────────────────────┐ │
│  │ Core Process│    │    WebView Process           │ │
│  │   (Rust)    │◄──►│  (系统原生 WebView)           │ │
│  │             │IPC │  HTML / CSS / JS             │ │
│  └─────────────┘    └─────────────────────────────┘ │
│                                                     │
│  打包体积:~3-10 MB(复用系统 WebView)               │
│  内存占用:~30-80 MB                                 │
└─────────────────────────────────────────────────────┘

关键差异#

维度

Electron

Tauri

后端语言

JavaScript (Node.js)

Rust

渲染引擎

自带 Chromium

系统 WebView (WebKit/WebView2/WebKitGTK)

打包体积

150 MB+

3-10 MB

内存占用

100-300 MB

30-80 MB

安全模型

Node.js 拥有完整系统权限

最小权限 + 能力声明

跨平台 WebView

一致(Chromium)

不同平台不同引擎

生态成熟度

非常成熟

快速成长中


10.2 Tauri 的双进程模型#

Tauri 应用由两个核心进程组成:

┌──────────────────────────────────────────────────────────┐
│                    Tauri 应用                              │
│                                                          │
│  ┌────────────────────────┐  IPC Bridge  ┌─────────────┐ │
│  │     Core Process       │◄────────────►│  WebView     │ │
│  │     (Rust 后端)         │              │  (前端 UI)   │ │
│  │                        │   invoke()   │             │ │
│  │  • 业务逻辑            │◄─────────────│  • HTML     │ │
│  │  • 文件系统访问         │              │  • CSS      │ │
│  │  • 数据库操作           │   emit()     │  • JS/TS    │ │
│  │  • 网络请求            │─────────────►│  • React    │ │
│  │  • 系统 API            │              │  • Vue      │ │
│  │  • 插件管理            │   listen()   │  • Svelte   │ │
│  │  • 安全策略            │◄─────────────│             │ │
│  └────────────────────────┘              └─────────────┘ │
│                                                          │
│  macOS: WKWebView    Windows: WebView2    Linux: WebKitGTK│
└──────────────────────────────────────────────────────────┘

10.2.1 Core Process(核心进程)#

Core Process 是用 Rust 编写的后端进程,负责:

  1. 应用生命周期管理 — 启动、运行、退出

  2. 窗口管理 — 创建、关闭、调整窗口

  3. 系统 API 访问 — 文件、网络、托盘、通知等

  4. IPC 处理 — 接收前端请求,返回结果

  5. 安全策略执行 — 权限检查、CSP 策略

// src-tauri/src/main.rs — Core Process 入口
fn main() {
    tauri::Builder::default()
        // 注册插件
        .plugin(tauri_plugin_shell::init())
        .plugin(tauri_plugin_fs::init())
        // 注册命令(供前端 invoke 调用)
        .invoke_handler(tauri::generate_handler![
            greet,
            read_config,
            save_note,
        ])
        // 管理全局状态
        .manage(AppState::default())
        // 配置窗口创建回调
        .setup(|app| {
            println!("Hive 应用启动!");
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

10.2.2 WebView Process(WebView 进程)#

WebView Process 负责渲染用户界面:

  • macOS — 使用 WKWebView(Safari 内核)

  • Windows — 使用 WebView2(Edge/Chromium 内核)

  • Linux — 使用 WebKitGTK

// src/main.js — 前端入口
import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';

// 调用 Rust 后端命令
const result = await invoke('greet', { name: 'Walter' });
console.log(result); // "Hello, Walter!"

// 监听后端事件
await listen('file-changed', (event) => {
    console.log('文件变更:', event.payload);
});

10.2.3 为什么是双进程?#

┌─────────────────────────────────────────────┐
│              安全边界(Sandbox)               │
│                                             │
│  WebView 进程                Core 进程       │
│  ┌───────────┐              ┌───────────┐   │
│  │ 只能渲染   │   IPC 桥     │ 可访问     │   │
│  │ HTML/CSS  │◄────────────►│ 系统资源   │   │
│  │ /JS       │  权限检查     │ 文件/网络  │   │
│  │           │              │ 数据库     │   │
│  │ 无法直接   │              │           │   │
│  │ 访问文件系统│              │ 按需授权   │   │
│  └───────────┘              └───────────┘   │
└─────────────────────────────────────────────┘

核心原则:最小权限(Principle of Least Privilege)

  • WebView 默认没有任何系统权限

  • 每个能力都需要显式声明

  • Core Process 作为"守门人"验证每个请求


10.3 IPC 通信机制概览#

Tauri 提供两种 IPC 通信模式:

10.3.1 Command 模式(请求-响应)#

前端通过 invoke() 调用 Rust 命令,等待返回结果:

前端 (JS)                          后端 (Rust)
   │                                   │
   │  invoke('save_note', {content})   │
   │──────────────────────────────────►│
   │                                   │  fn save_note(content)
   │                                   │  → 写入文件
   │                                   │  → 返回 Result
   │       Ok("saved") / Err(...)      │
   │◄──────────────────────────────────│
   │                                   │

Rust 端:

#[tauri::command]
async fn save_note(content: String) -> Result<String, String> {
    std::fs::write("note.md", &content)
        .map_err(|e| e.to_string())?;
    Ok("saved".to_string())
}

前端:

try {
    const result = await invoke('save_note', { content: '# Hello' });
    console.log(result); // "saved"
} catch (error) {
    console.error('保存失败:', error);
}

10.3.2 Event 模式(发布-订阅)#

适用于后端主动推送、双向通知的场景:

前端 (JS)                          后端 (Rust)
   │                                   │
   │  listen('download-progress')      │
   │  ┌──────────────────────────┐     │
   │  │ 注册监听器               │     │
   │  └──────────────────────────┘     │
   │                                   │
   │       emit('download-progress',   │
   │            { percent: 30 })       │
   │◄──────────────────────────────────│
   │                                   │
   │       emit('download-progress',   │
   │            { percent: 70 })       │
   │◄──────────────────────────────────│
   │                                   │
   │       emit('download-progress',   │
   │            { percent: 100 })      │
   │◄──────────────────────────────────│

Rust 端发送事件:

use tauri::Emitter;

#[tauri::command]
async fn download_file(app: tauri::AppHandle, url: String) -> Result<(), String> {
    for i in (0..=100).step_by(10) {
        // 模拟下载进度
        tokio::time::sleep(std::time::Duration::from_millis(200)).await;
        app.emit("download-progress", serde_json::json!({
            "percent": i
        })).map_err(|e| e.to_string())?;
    }
    Ok(())
}

前端监听事件:

import { listen } from '@tauri-apps/api/event';

const unlisten = await listen('download-progress', (event) => {
    const { percent } = event.payload;
    updateProgressBar(percent);
});

// 不再需要时取消监听
// unlisten();

10.3.3 两种模式对比#

维度

Command (invoke)

Event (emit/listen)

方向

前端 → 后端 → 前端

双向

模式

请求-响应

发布-订阅

返回值

有(Result)

无(fire-and-forget)

适用场景

CRUD 操作、查询

进度通知、状态变更、实时推送

类比

REST API

WebSocket / SSE


10.4 Tauri 的安全模型#

安全是 Tauri 的核心设计理念之一。

10.4.1 能力系统(Capabilities)#

Tauri 2.0 引入了声明式的能力系统:

// src-tauri/capabilities/default.json
{
  "identifier": "default",
  "description": "默认能力集",
  "windows": ["main"],
  "permissions": [
    "core:default",
    "shell:allow-open",
    "fs:allow-read-text-file",
    "fs:allow-write-text-file",
    {
      "identifier": "fs:scope",
      "allow": [
        "$APPDATA/**",
        "$DOCUMENT/**"
      ]
    }
  ]
}

10.4.2 安全层次#

┌─────────────────────────────────────────────┐
│            Tauri 安全模型(四层防御)          │
│                                             │
│  Layer 4: CSP(内容安全策略)                 │
│  ┌─────────────────────────────────────┐    │
│  │ 限制 JS 可加载的资源来源              │    │
│  └─────────────────────────────────────┘    │
│                                             │
│  Layer 3: Capabilities(能力声明)            │
│  ┌─────────────────────────────────────┐    │
│  │ 声明窗口可使用的 API 权限             │    │
│  └─────────────────────────────────────┘    │
│                                             │
│  Layer 2: IPC 过滤                          │
│  ┌─────────────────────────────────────┐    │
│  │ 只有注册的命令才能被调用              │    │
│  └─────────────────────────────────────┘    │
│                                             │
│  Layer 1: 进程隔离                          │
│  ┌─────────────────────────────────────┐    │
│  │ WebView 无法直接访问系统资源          │    │
│  └─────────────────────────────────────┘    │
└─────────────────────────────────────────────┘

10.4.3 与 Electron 安全对比#

维度

Electron

Tauri

默认权限

Node.js 拥有完整系统权限

WebView 默认无权限

权限控制

需手动配置 contextIsolation

声明式 Capabilities

远程代码

可通过 require() 执行任意代码

CSP 严格限制

文件访问

默认可访问整个文件系统

需声明 scope 范围


10.5 Tauri 应用的生命周期#

┌──────────────────────────────────────────────────┐
│              Tauri 应用生命周期                     │
│                                                  │
│  ┌─────────┐                                     │
│  │  启动    │ main() → tauri::Builder             │
│  └────┬────┘                                     │
│       ▼                                          │
│  ┌─────────┐                                     │
│  │  setup   │ .setup(|app| { ... })              │
│  │  初始化   │ 注册插件、初始化状态、创建窗口        │
│  └────┬────┘                                     │
│       ▼                                          │
│  ┌─────────┐                                     │
│  │  运行    │ 事件循环(Event Loop)               │
│  │         │ 处理 IPC、窗口事件、系统事件           │
│  └────┬────┘                                     │
│       ▼                                          │
│  ┌─────────┐                                     │
│  │  退出    │ on_window_event(CloseRequested)     │
│  │         │ 清理资源、保存状态                    │
│  └─────────┘                                     │
└──────────────────────────────────────────────────┘

生命周期钩子#

fn main() {
    tauri::Builder::default()
        // 1. setup — 应用初始化
        .setup(|app| {
            println!("✅ 应用初始化");

            // 获取应用数据目录
            let app_dir = app.path().app_data_dir()
                .expect("无法获取应用数据目录");
            std::fs::create_dir_all(&app_dir).ok();

            // 创建额外窗口
            let _settings_window = tauri::WebviewWindowBuilder::new(
                app,
                "settings",
                tauri::WebviewUrl::App("settings.html".into()),
            )
            .title("设置")
            .inner_size(600.0, 400.0)
            .build()?;

            Ok(())
        })
        // 2. on_window_event — 窗口事件
        .on_window_event(|window, event| {
            match event {
                tauri::WindowEvent::CloseRequested { api, .. } => {
                    println!("窗口 {} 请求关闭", window.label());
                    // 可以阻止关闭:api.prevent_close();
                }
                tauri::WindowEvent::Focused(focused) => {
                    println!("窗口 {} 焦点: {}", window.label(), focused);
                }
                _ => {}
            }
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

10.6 Tauri 项目结构深度解析#

hive/
├── src-tauri/                    # Rust 后端
│   ├── Cargo.toml                # Rust 依赖管理
│   ├── tauri.conf.json           # Tauri 核心配置
│   ├── capabilities/             # 能力声明(安全策略)
│   │   └── default.json
│   ├── icons/                    # 应用图标
│   │   ├── icon.ico
│   │   ├── icon.png
│   │   └── icon.icns
│   ├── src/
│   │   ├── main.rs               # 入口(桌面端)
│   │   ├── lib.rs                # 核心库(可被测试引用)
│   │   ├── commands/             # IPC 命令模块
│   │   │   ├── mod.rs
│   │   │   ├── notes.rs
│   │   │   └── settings.rs
│   │   ├── models/               # 数据模型
│   │   │   ├── mod.rs
│   │   │   └── note.rs
│   │   └── state.rs              # 全局状态
│   └── build.rs                  # 构建脚本
│
├── src/                          # 前端代码
│   ├── index.html
│   ├── main.js                   # 或 main.ts
│   ├── styles.css
│   ├── components/
│   └── pages/
│
├── package.json                  # 前端依赖
└── vite.config.js                # 前端构建配置

tauri.conf.json 核心配置#

{
  "productName": "Hive",
  "version": "0.1.0",
  "identifier": "com.example.hive",
  "build": {
    "frontendDist": "../dist",
    "devUrl": "http://localhost:5173",
    "beforeDevCommand": "npm run dev",
    "beforeBuildCommand": "npm run build"
  },
  "app": {
    "windows": [
      {
        "label": "main",
        "title": "Hive",
        "width": 1024,
        "height": 768,
        "resizable": true,
        "fullscreen": false
      }
    ],
    "security": {
      "csp": "default-src 'self'; script-src 'self'"
    }
  },
  "bundle": {
    "active": true,
    "targets": "all",
    "icon": [
      "icons/32x32.png",
      "icons/128x128.png",
      "icons/icon.icns",
      "icons/icon.ico"
    ]
  }
}

10.7 从 C++/Java 架构师视角看 Tauri#

与 C++ Qt 对比#

维度

Qt

Tauri

UI 技术

QML / Widgets (C++)

HTML/CSS/JS

后端语言

C++

Rust

信号-槽

Qt Signal/Slot

Command + Event

跨平台

编译时适配

运行时 WebView 适配

包管理

qmake / CMake

Cargo + npm

学习曲线

陡峭(MOC、QObject 体系)

中等(Web 前端 + Rust)

与 Java Swing/JavaFX 对比#

维度

JavaFX

Tauri

UI 技术

FXML / CSS

HTML/CSS/JS

后端语言

Java

Rust

事件模型

EventHandler

Command + Event

打包

jlink / jpackage (~50 MB+)

tauri build (~5 MB)

性能

JVM 启动慢

原生启动快


10.8 Hive 项目架构设计#

在接下来的章节中,我们将逐步构建 Hive 项目。这里先给出整体架构:

┌─────────────────────────────────────────────────────┐
│                    Hive 架构                         │
│                                                     │
│  ┌─────────────────────────────────────────────────┐│
│  │                 前端 (WebView)                   ││
│  │                                                 ││
│  │  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────────┐   ││
│  │  │ 笔记  │  │ 聊天  │  │ 设置  │  │ 插件面板  │   ││
│  │  │ 编辑器│  │ 窗口  │  │ 页面  │  │          │   ││
│  │  └──┬───┘  └──┬───┘  └──┬───┘  └────┬─────┘   ││
│  │     │         │         │            │         ││
│  │     └─────────┴─────────┴────────────┘         ││
│  │                    │ invoke() / listen()        ││
│  └────────────────────┼───────────────────────────┘│
│                       │ IPC Bridge                  │
│  ┌────────────────────┼───────────────────────────┐│
│  │                 后端 (Rust)                      ││
│  │                    │                            ││
│  │  ┌────────────┐  ┌┴───────────┐  ┌──────────┐ ││
│  │  │ 命令处理器  │  │ 事件分发器  │  │ 插件管理器│ ││
│  │  └─────┬──────┘  └─────┬──────┘  └────┬─────┘ ││
│  │        │               │               │       ││
│  │  ┌─────┴───────────────┴───────────────┴─────┐ ││
│  │  │              服务层 (Service)               │ ││
│  │  │  NoteService  ChatService  ConfigService   │ ││
│  │  └─────────────────┬─────────────────────────┘ ││
│  │                    │                            ││
│  │  ┌─────────────────┴─────────────────────────┐ ││
│  │  │              存储层 (Storage)               │ ││
│  │  │  SQLite    FileSystem    HTTP Client        │ ││
│  │  └───────────────────────────────────────────┘ ││
│  └────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────┘

10.9 小结#

本章我们从宏观视角了解了 Tauri 的架构设计:

核心知识点#

概念

要点

双进程模型

Core Process (Rust) + WebView Process (系统原生)

IPC 通信

Command(请求-响应)+ Event(发布-订阅)

安全模型

四层防御:进程隔离 → IPC 过滤 → Capabilities → CSP

生命周期

setup → 事件循环 → 退出清理

项目结构

src-tauri/ (Rust) + src/ (前端) + tauri.conf.json

Tauri 设计哲学#

┌────────────────────────────────────────┐
│         Tauri 设计哲学                  │
│                                        │
│  🔒 安全优先 — 最小权限原则             │
│  📦 轻量打包 — 复用系统 WebView         │
│  🦀 性能保障 — Rust 零成本抽象          │
│  🌐 Web 生态 — 复用前端技术栈           │
│  🔌 可扩展   — 插件系统                 │
└────────────────────────────────────────┘

下一章预告#

第十一章我们将深入 前后端通信,详细学习 #[tauri::command] 的各种用法、参数传递、状态管理,以及事件系统的高级模式。