关于 understanding-tauri-architecture
面向 Tauri 开发者的桌面应用架构参考文档,介绍 Rust 核心、WebView 前端、IPC 通信及分层安全模型。
主要功能
- 01核心与外壳架构
- 02Rust 后端职责
- 03原生 WebView 集成
- 04命令与事件 IPC
- 05能力与权限模型
适用场景
- 01理解 Tauri 应用分层
- 02设计前后端通信方式
- 03检查 Tauri 权限边界
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dchuk/ claude-code-tauri-skills --skill understanding-tauri-architecture安装后在 Claude Code 中输入/understanding-tauri-architecture确认已加载。
详细介绍
Tauri 架构
Tauri 是一套多语言工具包,用于构建桌面应用。它将 Rust 后端与在原生 WebView 中渲染的 HTML/CSS/JavaScript 相结合。本文介绍基本的架构概念。
架构概览
+------------------------------------------------------------------+
| TAURI APPLICATION |
+------------------------------------------------------------------+
| |
| +---------------------------+ +---------------------------+ |
| | FRONTEND (Shell) | | BACKEND (Core) | |
| |---------------------------| |---------------------------| |
| | | | | |
| | HTML / CSS / JavaScript | | Rust Code | |
| | (or any web framework) | | (tauri crate + app) | |
| | | | | |
| | - React, Vue, Svelte, | | - System access | |
| | Solid, etc. | | - File operations | |
| | - Standard web APIs | | - Native features | |
| | - Tauri JS API | | - Plugin system | |
| | | | | |
| +-------------+-------------+ +-------------+-------------+ |
| | | |
| | IPC (Message Passing) | |
| +<------------------------------->+ |
| | Commands & Events | |
| |
| +------------------------------------------------------------+ |
| | WEBVIEW (TAO + WRY) | |
| |------------------------------------------------------------| |
| | - Platform-native webview (not bundled) | |
| | - Windows: WebView2 (Edge/Chromium) | |
| | - macOS: WKWebView (Safari/WebKit) | |
| | - Linux: WebKitGTK | |
| +------------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| OPERATING SYSTEM |
| - Windows, macOS, Linux, iOS, Android |
+------------------------------------------------------------------+
核心与外壳设计
Tauri 采用核心-外壳架构,将应用拆分为两个不同的层:
核心(Rust 后端)
核心是基于 Rust 的后端,负责处理所有系统级操作:
- 系统访问:文件系统、网络、进程
- 原生功能:通知、对话框、剪贴板
- 安全保障:权限验证、能力检查
- 插件管理:通过插件扩展功能
- 应用生命周期:窗口管理、更新、配置
核心绝不会向前端开放直接的系统访问权限。所有交互都通过经过验证的 IPC 通道进行。
外壳(前端)
外壳是在 WebView 中渲染的用户界面层:
- Web 技术:HTML、CSS、JavaScript/TypeScript
- 框架无关:支持 React、Vue、Svelte、Solid 或原生 JS
- 沙箱执行:在 WebView 的安全沙箱中运行
- Tauri API 访问:通过
@tauri-apps/api调用后端
生态系统核心组件
tauri Crate
核心协调组件,负责:
- 在编译时读取
tauri.conf.json - 管理注入 WebView 的脚本
- 提供系统交互 API
- 处理应用更新
- 集成运行时、宏和实用工具
tauri-runtime
Tauri 与底层 WebView 库之间的衔接层。它抽象了特定于平台的 WebView 交互,使 Tauri 的其余部分能够保持平台无关。
tauri-macros 和 tauri-codegen
生成编译时代码,用于:
- 命令处理器(
#[tauri::command]) - 上下文和配置解析
- 资源嵌入与压缩
TAO(窗口管理)
跨平台窗口创建库(从 Winit 分叉而来):
- 创建和管理应用窗口
- 处理菜单栏和系统托盘
- 支持 Windows、macOS、Linux、iOS、Android
WRY(WebView 渲染)
跨平台 WebView 渲染库:
- 抽象各平台的 WebView 实现
- 处理 WebView 与原生代码之间的通信
- 管理 JavaScript 求值和事件桥接
WebView 集成
Tauri 使用操作系统的原生 WebView,而不是捆绑浏览器引擎:
+-------------------+---------------------------+
| Platform | WebView Engine |
+-------------------+---------------------------+
| Windows | WebView2 (Edge/Chromium) |
| macOS | WKWebView (Safari/WebKit) |
| Linux | WebKitGTK |
| iOS | WKWebView |
| Android | Android WebView |
+-------------------+---------------------------+
原生 WebView 的优势
- 二进制文件更小:无需捆绑浏览器引擎(约 600KB,而非约 150MB)
- 安全性:操作系统供应商修补 WebView 漏洞的速度,比应用开发者重新构建应用更快
- 性能:与操作系统原生集成
- 一致性:用户看到熟悉的渲染行为
注意事项
- 不同平台之间的渲染略有差异
- 功能是否可用取决于操作系统 WebView 版本
- 测试应覆盖所有目标平台
进程间通信(IPC)
Tauri 通过异步消息传递实现前端与后端之间的通信。这比共享内存更安全,因为核心可以拒绝恶意请求。
IPC 流程图
+------------------+ +------------------+
| Frontend | | Rust Backend |
| (JavaScript) | | (Core) |
+--------+---------+ +--------+---------+
| |
| 1. invoke('command', {args}) |
+---------------------------------------->|
| |
| [Request serialized as JSON-RPC] |
| |
| 2. Validate request |
| 3. Check permissions |
| 4. Execute command |
| |
| 5. Return Result<T, E> |
|<----------------------------------------+
| |
| [Response serialized as JSON] |
| |
两种 IPC 原语
命令(请求-响应)
类型安全的前端到后端函数调用:
// Rust backend
#[tauri::command]
fn greet(name: String) -> String {
format!("Hello, {}!", name)
}
// Register in builder
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
// JavaScript frontend
import { invoke } from '@tauri-apps/api/core';
const greeting = await invoke('greet', { name: 'World' });
console.log(greeting); // "Hello, World!"
主要特征:
- 基于 JSON-RPC 协议
- 所有参数都必须可序列化为 JSON
- 返回一个 Promise,成功时会以结果完成
- 支持异步 Rust 函数
- 可以访问应用状态、窗口句柄等
事件(即发即弃)
双向异步通知:
// Frontend: emit event
import { emit } from '@tauri-apps/api/event';
emit('user-action', { action: 'clicked' });
// Frontend: listen for events
import { listen } from '@tauri-apps/api/event';
const unlisten = await listen('download-progress', (event) => {
console.log(event.payload);
});
// Backend: listen for events
use tauri::Listener;
app.listen("user-action", |event| {
println!("User action: {}", event.payload());
});
// Backend: emit events
app.emit("download-progress", 50)?;
主要特征:
- 无返回值(单向)
- 前端和后端都可以发送或监听
- 最适合用于生命周期事件和状态变化
- 不会在编译时进行类型检查
安全模型概览
Tauri 采用多层安全机制,保护应用和用户的系统。
信任边界模型
+------------------------------------------------------------------+
| UNTRUSTED ZONE |
| +------------------------------------------------------------+ |
| | WebView Frontend | |
| | - JavaScript code (potentially from remote sources) | |
| | - User input | |
| | - Third-party libraries | |
| +------------------------------------------------------------+ |
+------------------------------------------------------------------+
|
[TRUST BOUNDARY]
[IPC Layer validates all requests]
|
+------------------------------------------------------------------+
| TRUSTED ZONE |
| +------------------------------------------------------------+ |
| | Rust Backend | |
| | - Your Rust code | |
| | - Tauri core | |
| | - System access (gated by permissions) | |
| +------------------------------------------------------------+ |
+------------------------------------------------------------------+
安全层
- WebView 沙箱:前端代码在 WebView 的安全沙箱中运行
- IPC 验证:验证所有跨越信任边界的消息
- Capabilities:定义每个窗口可访问的权限
- 权限:对允许执行的操作进行细粒度控制
- 作用域:限制命令行为(例如,将文件访问限制在特定目录中)
- CSP:内容安全策略限制前端代码可执行的操作
Capabilities 系统
Capabilities 控制授予特定窗口的权限:
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "main-window-capability",
"description": "Permissions for the main application window",
"windows": ["main"],
"permissions": [
"core:path:default",
"core:window:allow-set-title",
"fs:read-files",
"fs:scope-app-data"
]
}
Capabilities 在 src-tauri/capabilities/ 中以 JSON 或 TOML 文件定义。
权限结构
Capability
|
+-- windows: ["main", "settings"] // Which windows
|
+-- permissions: // What's allowed
|
+-- "plugin:action" // Allow specific action
+-- "plugin:scope-xxx" // Scope restrictions
默认安全态势
- 默认拒绝:必须明确允许命令
- 不允许远程访问:默认情况下,只有打包的代码才能访问 Tauri API
- 窗口隔离:每个窗口都有自己的 capabilities 集合
- 编译时检查:许多安全配置会在构建时验证
Rust 后端结构
典型的 Tauri 后端采用以下结构:
src-tauri/
+-- Cargo.toml # Rust dependencies
+-- tauri.conf.json # Tauri configuration
+-- capabilities/ # Permission definitions
| +-- main.json
+-- src/
+-- main.rs # Entry point (desktop)
+-- lib.rs # Core app logic
+-- commands/ # Command modules
| +-- mod.rs
| +-- file_ops.rs
+-- state.rs # App state management
入口点模式
// src-tauri/src/lib.rs
mod commands;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_shell::init())
.invoke_handler(tauri::generate_handler![
commands::greet,
commands::read_file,
])
.manage(AppState::default())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
命令模式
// Basic command
#[tauri::command]
fn simple_command() -> String {
"Hello".into()
}
// With arguments (camelCase from JS, snake_case in Rust)
#[tauri::command]
fn with_args(user_name: String, age: u32) -> String {
format!("{} is {} years old", user_name, age)
}
// With error handling
#[tauri::command]
fn fallible() -> Result<String, String> {
Ok("Success".into())
}
// Async command
#[tauri::command]
async fn async_command() -> Result<String, String> {
tokio::time::sleep(Duration::from_secs(1)).await;
Ok("Done".into())
}
// Accessing app state
#[tauri::command]
fn with_state(state: tauri::State<'_, AppState>) -> String {
state.get_value()
}
// Accessing window
#[tauri::command]
fn with_window(window: tauri::WebviewWindow) -> String {
window.label().to_string()
}
不捆绑运行时
Tauri 不会附带运行时。最终二进制文件:
- 将 Rust 代码直接编译为本机机器码
- 将前端资源嵌入二进制文件
- 使用系统原生 WebView
- 生成小巧、快速的可执行文件
与捆绑了 JavaScript 的 Electron 应用相比,这使得对 Tauri 应用进行逆向工程并非易事。
总结
| 组件 | 角色 |
|---|---|
| 核心(Rust) | 系统访问、安全、业务逻辑 |
| 外壳(前端) | UI 渲染、用户交互 |
| WebView(TAO+WRY) | 平台原生渲染桥接层 |
| IPC(命令/事件) | 在各层之间安全地传递消息 |
| Capabilities | 控制每个窗口的权限 |
该架构优先考虑:
- 安全性:多层保护、信任边界
- 性能:原生代码、不捆绑运行时
- 体积:尽可能缩小二进制文件
- 灵活性:支持任何前端框架,提供强大的 Rust 后端