tauri-desktop
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTauri Desktop Skill
Tauri 桌面与移动应用开发
Build lightweight, secure desktop (and mobile) apps with Tauri 2.0 — Rust backend, web frontend.
使用Tauri 2.0构建轻量、安全的桌面(及移动)应用——基于Rust后端与Web前端。
Why Tauri
为什么选择Tauri
| Feature | Tauri | Electron |
|---|---|---|
| Bundle size | 2-10 MB | 80-150 MB |
| Memory usage | 30-80 MB | 100-300 MB |
| Backend language | Rust | Node.js |
| Security model | Capability-based permissions | Full Node.js access |
| Mobile support | Yes (Tauri 2.0) | No |
| Auto-updater | Built-in | electron-updater |
| 特性 | Tauri | Electron |
|---|---|---|
| 包体积 | 2-10 MB | 80-150 MB |
| 内存占用 | 30-80 MB | 100-300 MB |
| 后端语言 | Rust | Node.js |
| 安全模型 | 基于能力的权限机制 | 完整Node.js访问权限 |
| 移动端支持 | 支持(Tauri 2.0) | 不支持 |
| 自动更新 | 内置功能 | electron-updater插件 |
Project Structure
项目结构
project/
├── src/ # Frontend (any web framework)
│ ├── main.ts
│ ├── App.tsx # React/Vue/Svelte/vanilla
│ └── styles.css
├── src-tauri/ # Rust backend
│ ├── src/
│ │ ├── main.rs # Entry point
│ │ ├── lib.rs # Commands and setup
│ │ └── commands/ # IPC command modules
│ │ ├── mod.rs
│ │ └── files.rs
│ ├── capabilities/ # Security permissions
│ │ └── default.json
│ ├── icons/ # App icons
│ ├── Cargo.toml # Rust dependencies
│ └── tauri.conf.json # Tauri configuration
├── package.json
├── vite.config.ts # Frontend bundler
└── tsconfig.jsonproject/
├── src/ # 前端(支持任意Web框架)
│ ├── main.ts
│ ├── App.tsx # React/Vue/Svelte/原生JS均可
│ └── styles.css
├── src-tauri/ # Rust后端
│ ├── src/
│ │ ├── main.rs # 入口文件
│ │ ├── lib.rs # 命令与配置
│ │ └── commands/ # IPC命令模块
│ │ ├── mod.rs
│ │ └── files.rs
│ ├── capabilities/ # 安全权限配置
│ │ └── default.json
│ ├── icons/ # 应用图标
│ ├── Cargo.toml # Rust依赖管理
│ └── tauri.conf.json # Tauri配置文件
├── package.json
├── vite.config.ts # 前端打包工具配置
└── tsconfig.jsonIPC Commands
IPC命令
Rust Side (Backend)
Rust端(后端)
rust
// src-tauri/src/lib.rs
use tauri::Manager;
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! From Rust.", name)
}
#[tauri::command]
async fn read_file(path: String) -> Result<String, String> {
std::fs::read_to_string(&path).map_err(|e| e.to_string())
}
#[tauri::command]
async fn save_settings(
app: tauri::AppHandle,
settings: serde_json::Value,
) -> Result<(), String> {
let path = app.path().app_config_dir().map_err(|e| e.to_string())?;
std::fs::create_dir_all(&path).map_err(|e| e.to_string())?;
let file = path.join("settings.json");
std::fs::write(file, settings.to_string()).map_err(|e| e.to_string())
}
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet, read_file, save_settings])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}rust
// src-tauri/src/lib.rs
use tauri::Manager;
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! From Rust.", name)
}
#[tauri::command]
async fn read_file(path: String) -> Result<String, String> {
std::fs::read_to_string(&path).map_err(|e| e.to_string())
}
#[tauri::command]
async fn save_settings(
app: tauri::AppHandle,
settings: serde_json::Value,
) -> Result<(), String> {
let path = app.path().app_config_dir().map_err(|e| e.to_string())?;
std::fs::create_dir_all(&path).map_err(|e| e.to_string())?;
let file = path.join("settings.json");
std::fs::write(file, settings.to_string()).map_err(|e| e.to_string())?;
Ok(())
}
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet, read_file, save_settings])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}Frontend Side (TypeScript)
前端(TypeScript)
typescript
import { invoke } from '@tauri-apps/api/core';
// Call Rust commands from frontend
const greeting = await invoke<string>('greet', { name: 'World' });
const content = await invoke<string>('read_file', { path: '/tmp/test.txt' });
await invoke('save_settings', {
settings: { theme: 'dark', fontSize: 14 },
});typescript
import { invoke } from '@tauri-apps/api/core';
// 从前端调用Rust命令
const greeting = await invoke<string>('greet', { name: 'World' });
const content = await invoke<string>('read_file', { path: '/tmp/test.txt' });
await invoke('save_settings', {
settings: { theme: 'dark', fontSize: 14 },
});Security Model (Capabilities)
安全模型(基于能力的权限)
json
// src-tauri/capabilities/default.json
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Default app permissions",
"windows": ["main"],
"permissions": [
"core:default",
"dialog:default",
"fs:default",
{
"identifier": "fs:allow-read-text-file",
"allow": [{ "path": "$APPDATA/**" }]
},
{
"identifier": "fs:allow-write-text-file",
"allow": [{ "path": "$APPDATA/**" }]
}
]
}Key security principles:
- Allowlist by default: Frontend can only access explicitly permitted APIs
- Scoped filesystem access: Restrict to specific directories
- No arbitrary shell access: Commands must be predefined in Rust
- CSP enforced: Content Security Policy headers set automatically
json
// src-tauri/capabilities/default.json
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "默认应用权限",
"windows": ["main"],
"permissions": [
"core:default",
"dialog:default",
"fs:default",
{
"identifier": "fs:allow-read-text-file",
"allow": [{ "path": "$APPDATA/**" }]
},
{
"identifier": "fs:allow-write-text-file",
"allow": [{ "path": "$APPDATA/**" }]
}
]
}核心安全原则:
- 默认白名单机制:前端仅能访问明确授权的API
- 文件系统访问范围限制:仅允许访问指定目录
- 无任意Shell访问权限:命令必须在Rust中预定义
- 强制启用CSP:自动设置内容安全策略头
Plugins (Tauri 2.0)
插件系统(Tauri 2.0)
toml
undefinedtoml
undefinedsrc-tauri/Cargo.toml
src-tauri/Cargo.toml
[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-dialog = "2"
tauri-plugin-fs = "2"
tauri-plugin-shell = "2"
tauri-plugin-store = "2"
tauri-plugin-updater = "2"
tauri-plugin-notification = "2"
```rust
// Register plugins
tauri::Builder::default()
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_store::Builder::new().build())
.plugin(tauri_plugin_updater::Builder::new().build())
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-dialog = "2"
tauri-plugin-fs = "2"
tauri-plugin-shell = "2"
tauri-plugin-store = "2"
tauri-plugin-updater = "2"
tauri-plugin-notification = "2"
```rust
// 注册插件
tauri::Builder::default()
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_store::Builder::new().build())
.plugin(tauri_plugin_updater::Builder::new().build())
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");Auto-Updater
自动更新
json
// src-tauri/tauri.conf.json (excerpt)
{
"plugins": {
"updater": {
"pubkey": "YOUR_PUBLIC_KEY",
"endpoints": [
"https://releases.example.com/{{target}}/{{arch}}/{{current_version}}"
]
}
}
}typescript
// Frontend update check
import { check } from '@tauri-apps/plugin-updater';
const update = await check();
if (update) {
await update.downloadAndInstall();
await relaunch();
}json
// src-tauri/tauri.conf.json(节选)
{
"plugins": {
"updater": {
"pubkey": "YOUR_PUBLIC_KEY",
"endpoints": [
"https://releases.example.com/{{target}}/{{arch}}/{{current_version}}"
]
}
}
}typescript
// 前端检查更新
import { check } from '@tauri-apps/plugin-updater';
const update = await check();
if (update) {
await update.downloadAndInstall();
await relaunch();
}Building and Distribution
构建与分发
bash
undefinedbash
undefinedDevelopment
开发模式
npm run tauri dev
npm run tauri dev
Build for current platform
为当前平台构建
npm run tauri build
npm run tauri build
Build for specific target
为指定目标平台构建
npm run tauri build --target x86_64-pc-windows-msvc
npm run tauri build --target aarch64-apple-darwin
npm run tauri build --target x86_64-unknown-linux-gnu
npm run tauri build --target x86_64-pc-windows-msvc
npm run tauri build --target aarch64-apple-darwin
npm run tauri build --target x86_64-unknown-linux-gnu
Mobile (Tauri 2.0)
移动端(Tauri 2.0)
npm run tauri android dev
npm run tauri ios dev
undefinednpm run tauri android dev
npm run tauri ios dev
undefinedDistribution Formats
分发格式
| Platform | Formats |
|---|---|
| macOS | .dmg, .app |
| Windows | .msi, .exe (NSIS) |
| Linux | .deb, .rpm, .AppImage |
| Android | .apk, .aab |
| iOS | .ipa |
| 平台 | 支持格式 |
|---|---|
| macOS | .dmg, .app |
| Windows | .msi, .exe (NSIS) |
| Linux | .deb, .rpm, .AppImage |
| Android | .apk, .aab |
| iOS | .ipa |
Development Tips
开发技巧
- Use to detect Tauri environment in frontend
window.__TAURI__ - State management: Use Tauri's for Rust-side state, frontend store for UI state
State - File dialogs: Use instead of browser file input
@tauri-apps/plugin-dialog - System tray: Configure in with menu items
tauri.conf.json - Multi-window: Create with from Rust or
WebviewWindow::new()from JSWebviewWindow.create()
- 在前端中使用检测Tauri运行环境
window.__TAURI__ - 状态管理:Rust端状态使用Tauri的,UI状态使用前端状态管理库
State - 文件对话框:使用替代浏览器原生文件输入
@tauri-apps/plugin-dialog - 系统托盘:在中配置菜单项
tauri.conf.json - 多窗口:通过Rust的或JS的
WebviewWindow::new()创建WebviewWindow.create()
Related Resources
相关资源
- - Rust language patterns
~/.claude/skills/rust/SKILL.md - - Desktop development agent
~/.claude/agents/desktop-developer.md - - Rust stack guide
~/.claude/docs/reference/stacks/rust.md
Small binaries. Strong security. Native performance. Web flexibility.
- - Rust语言模式指南
~/.claude/skills/rust/SKILL.md - - 桌面开发代理
~/.claude/agents/desktop-developer.md - - Rust技术栈指南
~/.claude/docs/reference/stacks/rust.md
体积小巧 · 安全性高 · 原生性能 · Web灵活性