创建第一个 Tauri 项目
# 使用 npm create(推荐)
npm create tauri-app@latest my-tauri-app
cd my-tauri-app
# 脚手架会询问以下问题:
# ? Choose which language to use for your frontend: TypeScript / JavaScript
# ? Choose your package manager: npm / yarn / pnpm / bun
# ? Choose your UI template: Vanilla / Vue / React / Svelte / Solid / Angular
# 安装依赖
npm install
# 启动开发模式(同时启动前端 dev server + Tauri 窗口)
npm run tauri dev
tauri dev 会:1) 启动前端框架的 dev server(如 Vite 的 localhost:1420);2) 编译 Rust 代码;3) 启动 Tauri 应用窗口,WebView 加载前端 dev server 的页面。修改前端代码会热更新,修改 Rust 代码会重新编译并重启窗口。
项目目录结构
my-tauri-app/
├── src/ # 前端源代码(你熟悉的 Web 世界)
│ ├── main.ts # 前端入口
│ ├── App.tsx # 根组件(React 示例)
│ └── assets/
├── src-tauri/ # Rust 后端(Tauri 核心)
│ ├── src/
│ │ ├── main.rs # Rust 入口,创建 Tauri App
│ │ └── lib.rs # Commands 和插件注册
│ ├── capabilities/ # 权限配置(Tauri 2.0 新增)
│ │ └── default.json # 默认窗口权限
│ ├── icons/ # 应用图标(多种尺寸)
│ ├── tauri.conf.json # Tauri 主配置文件
│ └── Cargo.toml # Rust 依赖管理
├── public/ # 静态资源(直接复制到产出)
├── index.html # Vite 入口 HTML
├── vite.config.ts # Vite 配置
├── package.json # 前端依赖
└── tsconfig.json # TypeScript 配置
tauri.conf.json 详解
这是 Tauri 的主配置文件,控制应用的方方面面:
{
"productName": "my-tauri-app",
"version": "0.1.0",
"identifier": "com.example.myapp", // 唯一应用ID(反向域名格式)
"build": {
"beforeDevCommand": "npm run dev", // dev 时先启动前端
"beforeBuildCommand": "npm run build", // build 时先构建前端
"devUrl": "http://localhost:1420", // dev 模式 WebView 加载地址
"frontendDist": "../dist" // 生产构建产出目录
},
"app": {
"windows": [
{
"label": "main",
"title": "My Tauri App",
"width": 1200,
"height": 800,
"minWidth": 800,
"minHeight": 600,
"resizable": true,
"fullscreen": false,
"decorations": true // false 则无边框窗口
}
],
"security": {
"csp": null // Content Security Policy(生产环境建议配置)
}
},
"bundle": {
"active": true,
"targets": "all", // 或 ["nsis", "dmg", "appimage"]
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/icon.icns", // macOS 图标
"icons/icon.ico" // Windows 图标
]
}
}
Cargo.toml:Rust 依赖管理
[package]
name = "my-tauri-app"
version = "0.1.0"
edition = "2021"
[lib]
name = "my_tauri_app_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-fs = "2"
tauri-plugin-dialog = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
[features]
default = ["custom-protocol"]
custom-protocol = ["tauri/custom-protocol"]
tauri://)加载前端资源,而非 HTTP 服务器。开发模式下禁用,使用 Vite dev server。cdylib(动态库)和 staticlib(静态库),rlib 用于 Rust 单元测试。Rust 入口文件
// src-tauri/src/main.rs
// 防止 Windows 弹出控制台窗口(生产模式)
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
// 调用 lib.rs 中定义的 run() 函数
my_tauri_app_lib::run();
}
// src-tauri/src/lib.rs
use tauri::Manager;
// 注册 Command(第4章详解)
#[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()
// 注册插件
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_dialog::init())
// 注册 Commands
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
开发与构建命令
npm run tauri dev
启动开发模式。同时运行前端 dev server 和 Tauri 窗口,支持前端热更新(HMR)。修改 Rust 代码会自动重新编译(约需 5-30 秒)。
npm run tauri build
生产构建。先运行 npm run build 构建前端,再用 cargo build --release 编译 Rust,最后用打包工具生成安装包(NSIS/dmg/AppImage)。
npm run tauri info
显示当前环境诊断信息:Tauri 版本、Rust 版本、Node 版本、WebView 版本、操作系统信息等。排查问题时的首选命令。
npm run tauri icon [path/to/app-icon.png]
从一张 1024x1024 的 PNG 图标自动生成所有平台需要的图标尺寸(32x32、128x128、.icns、.ico 等),输出到 src-tauri/icons/。
npm run tauri ios dev / tauri android dev
移动端开发模式。iOS 启动模拟器,Android 启动 AVD 或连接真机。需要预先完成移动端工具链配置。
capabilities/ 权限系统
// src-tauri/capabilities/default.json
{
"identifier": "default",
"description": "主窗口默认权限",
"windows": ["main"], // 适用于哪些窗口(label 列表)
"permissions": [
"core:default", // Tauri 核心默认权限
"fs:allow-read-text-file", // 允许读文本文件
"fs:allow-write-text-file",
"fs:scope" // 配合 scope 限制可访问路径
]
}
格式为 插件名:allow-动作名 或 插件名:deny-动作名。查看所有可用权限:cargo tauri permission list。也可以在 Tauri 文档的各插件页面中找到权限列表。
配置文件高级选项
{
"app": {
"windows": [{
"label": "main",
"title": "My App",
"width": 1200, "height": 800,
"minWidth": 800, "minHeight": 600,
"center": true,
"decorations": true, // false = 无边框窗口
"transparent": false, // 透明背景(需要 transparent feature)
"visible": true // false = 系统托盘应用不自动显示
}]
},
"bundle": {
"active": true,
"targets": "all", // 或指定 ["dmg", "msi", "deb"]
"identifier": "com.mycompany.myapp",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/icon.icns", // macOS
"icons/icon.ico" // Windows
],
"updater": {
"active": true,
"endpoints": ["https://releases.myapp.com/{{target}}/{{arch}}/{{current_version}}"],
"pubkey": "..." // 通过 tauri signer generate 生成
}
}
}
Rust 全局状态管理
Tauri 允许在 Rust 侧维护全局状态,通过 manage() 注册,在 Command 中通过 State 参数访问:
use std::sync::Mutex;
use tauri::State;
struct AppState {
counter: u32,
}
type SharedState = Mutex<AppState>;
#[tauri::command]
fn increment(state: State<'_', SharedState>) -> u32 {
let mut s = state.lock().unwrap();
s.counter += 1;
s.counter
}
#[tauri::command]
fn get_count(state: State<'_', SharedState>) -> u32 {
state.lock().unwrap().counter
}
fn main() {
tauri::Builder::default()
.manage(Mutex::new(AppState { counter: 0 }))
.invoke_handler(tauri::generate_handler![increment, get_count])
.run(tauri::generate_context!())
.unwrap();
}
Vite 配置与 Tauri 集成
vite.config.ts 关键配置
Tauri 项目的 Vite 配置需要特别注意几个关键选项,确保前端代码能正确加载系统资源和调用 Tauri API:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
// 是否在 Tauri 环境中运行
const host = process.env.TAURI_DEV_HOST;
export default defineConfig({
plugins: [react()],
// Vite dev server 配置
server: {
// Tauri 需要一个固定的主机名(不能用 localhost,移动端需要局域网 IP)
host: host ?? false,
port: 1420,
strictPort: true, // 端口被占用时报错而非自动换端口
// HMR 配置(Tauri 移动端开发需要)
hmr: host
? {
protocol: 'ws',
host,
port: 1421,
}
: undefined,
},
// 清除前端浏览器警告(Tauri API 不是浏览器 API)
envPrefix: ['VITE_', 'TAURI_'],
build: {
// 输出目录(与 tauri.conf.json 的 frontendDist 一致)
outDir: '../dist',
// Tauri 使用 Chromium,支持现代特性,不需要降级兼容
target: process.env.TAURI_ENV_PLATFORM == 'windows'
? 'chrome105'
: 'safari13',
// 开发构建禁用 minify,加快编译
minify: !process.env.TAURI_ENV_DEBUG ? 'esbuild' : false,
// 关闭 sourcemap(减小产出体积)
sourcemap: !!process.env.TAURI_ENV_DEBUG,
},
});
环境变量
区分开发和生产环境
Tauri 在不同场景下注入不同的环境变量,可以用来实现环境感知的行为:
// 前端代码中判断运行环境
// 是否在 Tauri 中运行(区别于纯 Web 浏览器)
const isTauri = '__TAURI_INTERNALS__' in window;
// 是否是 debug 构建(tauri dev 或 tauri build --debug)
const isDev = import.meta.env.DEV;
const isProd = import.meta.env.PROD;
const mode = import.meta.env.MODE; // "development" 或 "production"
// 用户自定义 VITE_ 前缀变量
// .env.development:
// VITE_API_URL=http://localhost:3000
// .env.production:
// VITE_API_URL=https://api.myapp.com
const apiUrl = import.meta.env.VITE_API_URL;
// Tauri 环境信息(由 Tauri 注入)
// process.env.TAURI_ENV_PLATFORM: "windows" | "linux" | "macos" | "ios" | "android"
// process.env.TAURI_ENV_ARCH: "x86_64" | "aarch64" | "i686" | "armv7"
// process.env.TAURI_ENV_DEBUG: "true" | undefined
const platform = import.meta.env.TAURI_ENV_PLATFORM;
// 根据平台显示不同内容
function getPlatformShortcut(action: string): string {
if (platform === 'macos') {
return `⌘${action}`;
}
return `Ctrl+${action}`;
}
// Rust 端获取环境信息
#[tauri::command]
fn get_app_info() -> serde_json::Value {
// CARGO_PKG_VERSION 在编译期替换为实际版本号
let version = env!("CARGO_PKG_VERSION");
// cfg! 宏:编译期条件(不影响运行时性能)
let is_debug = cfg!(debug_assertions);
let platform = if cfg!(target_os = "windows") {
"windows"
} else if cfg!(target_os = "macos") {
"macos"
} else {
"linux"
};
serde_json::json!({
"version": version,
"isDebug": is_debug,
"platform": platform,
})
}
开发效率提升
加速 Rust 编译
Tauri 的 Rust 编译(特别是首次)可能需要 2-5 分钟。以下方法可以显著加速:
# src-tauri/.cargo/config.toml(项目级 Cargo 配置)
[build]
# 使用 mold 链接器(Linux,速度是 ld 的 5-10 倍)
# rustflags = ["-C", "link-arg=-fuse-ld=mold"]
# macOS 使用 lld 链接器
# rustflags = ["-C", "link-arg=-fuse-ld=lld"]
[profile.dev]
# 开发模式优化:减少单文件优化,提高并行编译度
opt-level = 0
debug = true
[profile.dev.package."*"]
# 依赖库仍然用高优化级别(只有你自己的代码是 debug)
opt-level = 3
# 可选:cranelift 后端(更快的编译,但不适合生产)
# [unstable]
# codegen-backend = "cranelift"
# 工具链加速选项
# 安装 cargo-watch(自动检测变更并重新编译)
cargo install cargo-watch
# 使用 sccache 缓存编译结果(跨次构建复用)
cargo install sccache
export RUSTC_WRAPPER=sccache
# 查看编译耗时分解
cargo build --timings
# 只检查错误,不生成二进制(最快的语法检查)
cargo check
Rust 的增量编译已经相当智能——只有你修改的文件所在 Crate 会重新编译。但第一次和清空缓存后(cargo clean)会全量编译,这时候几分钟是正常的。避免在开发时频繁运行 cargo clean。如果修改的是 tauri.conf.json 等配置文件,无需重新编译 Rust,只需要重新运行 tauri dev。
- 项目结构:前端代码在根目录,Rust 后端在
src-tauri/;lib.rs是 Command 的主要位置,main.rs是入口;custom-protocolfeature 控制生产模式的资源加载方式。 - tauri.conf.json:控制窗口属性(大小、标题、透明度、decorations)、打包目标(targets)和应用 ID(identifier);beforeDevCommand/beforeBuildCommand 链接前后端构建流程。
- Capabilities 权限系统:最小权限原则,只授予需要的操作;权限格式为
插件名:allow-操作名;cargo tauri permission list查看所有可用权限。 - Rust 全局状态:
manage(Mutex::new(state))注册,Command 中通过State<'_, T>访问;异步 I/O 场景用tokio::sync::Mutex避免阻塞同步 Mutex。 - 环境变量:Vite 的
import.meta.env和 Rust 的env!()/cfg!()都支持环境区分;TAURI_ENV_PLATFORM可用于平台特定 UI 逻辑(如快捷键提示)。 - 编译加速:
.cargo/config.toml配置链接器(mold/lld);profile.dev.package."*"让依赖以高优化级别编译;sccache 缓存跨次构建的编译结果。