06
Tauri 2.0 跨端开发
Tauri 2.0 · Rust Backend + Web Frontend
Tauri 就是 Electron 的瘦身版。Electron 把整个 Chromium 塞进去,一个应用 200MB;Tauri 用系统自带的 WebView,包体 ~3MB,内存占用低一个数量级。Rust 写后端,Web 技术写前端,一套代码同时出 Windows / macOS / Linux / iOS / Android。
Tauri vs Electron
| 维度 | Tauri 2.0 | Electron |
| 包体 | ~3 MB | ~150-200 MB |
| 内存 | 几十 MB | 几百 MB |
| 后端语言 | Rust | Node.js |
| WebView | 系统 WebView(EdgeWK/WebKit) | 内置 Chromium |
| 安全性 | 权限白名单,默认最小权限 | Node 集成开关 |
| 移动端 | 2.0 起支持 iOS/Android | 有限 |
项目结构
my-app/
├── src/ # 前端(React/Vue/任意 Web 框架)
│ ├── App.tsx
│ └── main.tsx
└── src-tauri/ # Rust 后端
├── src/
│ └── main.rs # #[tauri::command] 命令
├── Cargo.toml
├── tauri.conf.json # Tauri 配置
└── capabilities/ # 权限配置(前端能调什么)
前后端通信核心:#[tauri::command]
// src-tauri/src/main.rs —— Rust 后端
#[tauri::command]
fn greet(name: &str) -> String {
format!("你好,{name}!")
}
#[tauri::command]
async fn fetch_data(url: String) -> Result<String, String> {
reqwest::get(&url).await.map_err(|e| e.to_string())?
.text().await.map_err(|e| e.to_string())
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet, fetch_data])
.run(tauri::generate_context!())
.expect("error");
}
// 前端 React —— 一行 invoke 调 Rust
import { invoke } from '@tauri-apps/api/core';
const msg = await invoke<string>('greet', { name: '小明' });
console.log(msg); // 你好,小明!
Rust 调用前端:emit 事件
Rust 主动推数据给前端(比如 AI 流式输出),用 app.emit(),前端 listen() 监听。这就是流式 LLM 输出在 Tauri 里的实现方式。
// Rust 端:流式生成 token,每个 token 推一次
app_handle.emit("llm-token", &token_string)?;
// 前端:监听
import { listen } from '@tauri-apps/api/event';
listen<string>('llm-token', e => appendToChat(e.payload));
核心插件
| 插件 | 能力 |
plugin-fs | 文件系统读写 |
plugin-dialog | 打开/保存文件对话框 |
plugin-notification | 系统通知 |
plugin-global-shortcut | 全局快捷键 |
plugin-http | 后端 HTTP 请求(绕过 CORS) |
plugin-os | 操作系统信息 |
updater | 应用自动更新(签名验证) |
窗口管理与系统托盘
桌面 AI 应用的标配:全局快捷键呼出主窗口,最小化到托盘,点托盘图标显示/隐藏。Tauri 的 window API 和 tray 插件都支持。
// Rust 端:创建主窗口,设置无边框/置顶
use tauri::Manager;
tauri::Builder::default()
.setup(|app| {
let win = app::get_window("main").unwrap();
win::set_title("AI 助手")?;
Ok(())
})
.system_tray(TrayIcon::new("main")
.icon(default_icon())
.on_tray_icon_event(|tray, event| {
if let TrayIconEvent::Click(..) = event {
let win = tray.window();
let _ = win::show();
let _ = win::set_focus();
}
})
)
打包发布
tauri build 一条命令出各平台安装包:Windows 的 NSIS .exe、macOS 的 .dmg、Linux 的 .AppImage。要上架商店(Mac App Store / Microsoft Store)需要代码签名。自动更新用 tauri-plugin-updater,先在本地用 ed25519 生成密钥对,发布时签名,客户端验证签名后才更新——防止中间人推恶意更新包。
坑:权限默认最小
Tauri 2.0 默认前端什么权限都没有。你要用 fs,必须在 capabilities/*.json 里显式授权。这是好事——比 Electron 安全多了,但新手会踩坑:调一个功能报 "permission denied"。去 capabilities 文件加权限就好。
记
本章小结
① Tauri = Rust 后端 + Web 前端 + 系统 WebView,包体 3MB,跨桌面 + 移动。
② 前端调 Rust:#[tauri::command] + invoke();Rust 推前端:emit() + listen()。
③ 安全靠 capabilities 权限白名单,插件按需装。