跳到主要内容

项目结构

理解 Tauri 项目的组织方式,有助于更好地开发和维护应用。

标准项目结构

使用 create-tauri-app 创建的典型项目结构如下:

my-tauri-app/
├── src/ # 前端代码目录
│ ├── main.ts # 前端入口文件
│ ├── style.css # 全局样式
│ └── index.html # HTML 模板
├── src-tauri/ # Tauri 后端代码目录
│ ├── src/
│ │ ├── main.rs # 桌面端入口(旧版)
│ │ └── lib.rs # 主库文件(新版)
│ ├── Cargo.toml # Rust 依赖配置
│ ├── tauri.conf.json # Tauri 配置文件
│ ├── capabilities/ # 权限配置目录
│ │ └── default.json
│ └── icons/ # 应用图标
├── package.json # Node.js 依赖
├── vite.config.ts # Vite 配置
└── index.html # 开发服务器入口

前端目录(src/)

前端代码可以使用任意框架(Vue、React、Svelte 等)或纯 HTML/CSS/JS。

典型前端文件

index.html - HTML 入口模板:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

main.ts - JavaScript/TypeScript 入口:

import { invoke } from "@tauri-apps/api/core";

// 调用 Rust 函数
async function greet(name: string) {
const response = await invoke("greet", { name });
console.log(response);
}

greet("World");

前端与 Tauri 的集成

前端通过 @tauri-apps/api 包与后端通信:

npm install @tauri-apps/api

主要 API 模块:

模块用途
@tauri-apps/api/core调用 Commands (invoke)
@tauri-apps/api/event事件系统 (emit, listen)
@tauri-apps/api/window窗口控制
@tauri-apps/api/dialog系统对话框
@tauri-apps/api/fs文件系统操作
@tauri-apps/api/notification系统通知

后端目录(src-tauri/)

这是 Tauri 应用的核心,包含 Rust 代码和配置。

Cargo.toml

Rust 项目的依赖配置文件:

[package]
name = "my-tauri-app"
version = "0.1.0"
edition = "2021"

[dependencies]
tauri = { version = "2", features = [] }
serde = { version = "1", features = ["derive"] }

[features]
default = ["custom-protocol"]
custom-protocol = ["tauri/custom-protocol"]

关键依赖说明:

  • tauri:核心框架
  • serde:序列化/反序列化,用于前后端数据传输
  • tokio:异步运行时(如需要异步操作)

tauri.conf.json

Tauri 应用的主配置文件:

{
"productName": "My App",
"version": "0.1.0",
"identifier": "com.example.myapp",
"build": {
"frontendDist": "../dist",
"devUrl": "http://localhost:5173",
"beforeDevCommand": "npm run dev",
"beforeBuildCommand": "npm run build"
},
"app": {
"windows": [
{
"title": "My App",
"width": 800,
"height": 600,
"resizable": true,
"fullscreen": false
}
],
"security": {
"csp": "default-src 'self'; script-src 'self'"
}
},
"bundle": {
"active": true,
"targets": ["msi", "dmg", "appimage"],
"icon": ["icons/32x32.png", "icons/128x128.png"]
}
}

配置项说明:

配置项说明
productName应用显示名称
identifier应用唯一标识符(反向域名格式)
build.frontendDist生产构建输出目录
build.devUrl开发服务器地址
app.windows窗口配置数组
app.security.csp内容安全策略
bundle.targets打包目标格式

lib.rs

Rust 后端的主入口文件:

// 引入 Tauri 宏和类型
use tauri::Manager;

// 定义一个 Command(可被前端调用)
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}

// 应用入口函数
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
// 注册 Commands
.invoke_handler(tauri::generate_handler![greet])
// 应用初始化
.setup(|app| {
// 获取主窗口
let main_window = app.get_webview_window("main").unwrap();

// 可以在这里进行初始化操作
println!("App is starting...");

Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

关键概念:

  • #[tauri::command]:标记函数可被前端调用
  • tauri::generate_handler!:注册多个 Commands
  • .setup():应用初始化钩子
  • tauri::generate_context!():加载配置上下文

capabilities/

权限配置目录,定义前端可以访问哪些系统功能:

default.json:

{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Default permissions",
"windows": ["main"],
"permissions": [
"core:default",
"dialog:allow-open",
"fs:allow-read"
]
}

权限系统确保前端只能访问明确授权的功能,这是 Tauri 安全模型的核心。

多窗口应用结构

对于多窗口应用,项目结构可能更复杂:

src-tauri/
├── src/
│ ├── lib.rs # 主入口
│ ├── commands/ # Commands 模块化
│ │ ├── mod.rs
│ │ ├── file.rs # 文件相关 Commands
│ │ └── window.rs # 窗口相关 Commands
│ ├── state.rs # 全局状态管理
│ └── error.rs # 错误类型定义
├── capabilities/
│ ├── default.json # 主窗口权限
│ └── settings.json # 设置窗口权限
└── tauri.conf.json

模块化 Commands

commands/mod.rs:

pub mod file;
pub mod window;

commands/file.rs:

use tauri::command;
use std::fs;

#[command]
pub fn read_file(path: String) -> Result<String, String> {
fs::read_to_string(&path).map_err(|e| e.to_string())
}

#[command]
pub fn write_file(path: String, content: String) -> Result<(), String> {
fs::write(&path, content).map_err(|e| e.to_string())
}

lib.rs 中注册:

mod commands;

.use commands::{file, window};

.invoke_handler(tauri::generate_handler![
file::read_file,
file::write_file,
window::create_settings_window,
])

配置文件详解

窗口配置

{
"app": {
"windows": [
{
"label": "main",
"title": "主窗口",
"width": 1200,
"height": 800,
"minWidth": 800,
"minHeight": 600,
"center": true,
"resizable": true,
"maximized": false,
"fullscreen": false,
"decorations": true,
"alwaysOnTop": false,
"visible": true,
"transparent": false,
"url": "index.html"
}
]
}
}

打包配置

{
"bundle": {
"active": true,
"targets": ["msi", "nsis", "dmg", "appimage", "deb", "rpm"],
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/[email protected]",
"icons/icon.icns",
"icons/icon.ico"
],
"resources": [],
"copyright": "© 2024 Your Name",
"category": "DeveloperTool",
"shortDescription": "A Tauri App",
"longDescription": "A longer description of your app"
}
}

开发工作流

开发模式

# 启动开发服务器(热重载)
npm run tauri dev

开发模式下:

  • 前端代码修改会自动刷新
  • Rust 代码修改会自动重新编译
  • 可以打开 DevTools 调试

生产构建

# 构建生产版本
npm run tauri build

输出位置:

  • Windows: src-tauri/target/release/bundle/msi/
  • macOS: src-tauri/target/release/bundle/dmg/
  • Linux: src-tauri/target/release/bundle/appimage/

最佳实践

  1. 分离关注点:将 Commands 按功能模块化
  2. 类型安全:使用 serde 定义数据传输类型
  3. 错误处理:定义统一的错误类型,避免直接暴露内部错误
  4. 状态管理:使用 tauri::State 管理全局状态
  5. 权限最小化:只授予必要的权限

下一步