Tauri 快速开始 - 15 分钟创建第一个应用
前言
环境搭建完成后,现在是时候动手创建你的第一个 Tauri 应用了!这篇文章会带你从零开始,15 分钟内创建一个完整的 Tauri 应用,包括前后端通信、文件操作等基本功能。
我还记得第一次创建 Tauri 应用时的兴奋感,当看到只有几 MB 的安装包,启动速度飞快的应用窗口,真的有种"相见恨晚"的感觉。今天,我也希望能把这份体验传递给你。
让我们开始吧!
创建项目
方式一:使用 create-tauri-app(推荐)
这是最简单快捷的方式:
bash
# 使用 npm
npm create tauri-app@latest
# 使用 yarn
yarn create tauri-app
# 使用 pnpm
pnpm create tauri-app交互式配置
运行命令后,会看到一系列提示:
bash
✔ Project name · my-tauri-app
✔ Choose which language to use for your frontend · TypeScript / JavaScript
✔ Choose your package manager · npm
✔ Choose your UI template · React
✔ Choose your UI flavor · TypeScript让我们逐一解释这些选项:
1. Project name(项目名称)
bash
✔ Project name · my-tauri-app
# 建议:
- 使用小写字母
- 用连字符分隔单词
- 避免空格和特殊字符2. Frontend Language(前端语言)
bash
✔ Choose which language to use for your frontend
› TypeScript / JavaScript
# TypeScript: 类型安全,大型项目推荐
# JavaScript: 简单直接,快速原型推荐3. Package Manager(包管理器)
bash
✔ Choose your package manager
› npm
› yarn
› pnpm
# npm: 最通用,Node.js 自带
# yarn: 速度快,离线支持好
# pnpm: 磁盘空间利用率高,速度快4. UI Template(前端框架)
bash
✔ Choose your UI template
› Vanilla # 原生 HTML/CSS/JS
› Vue # Vue 3
› Svelte # Svelte
› React # React
› Solid # SolidJS
› Angular # Angular
# 选择你最熟悉的框架
# 如果不确定,推荐 React 或 Vue我的推荐配置
对于初学者,我推荐这样配置:
bash
Project name: my-first-tauri-app
Frontend: TypeScript / JavaScript → TypeScript
Package Manager: npm
UI Template: React
UI Flavor: TypeScript项目结构详解
创建完成后,进入项目目录:
bash
cd my-first-tauri-app让我们看看项目结构:
my-first-tauri-app/
├── node_modules/ # Node.js 依赖
├── public/ # 静态资源
│ └── vite.svg # 示例图标
├── src/ # 前端源代码
│ ├── App.tsx # 主组件
│ ├── main.tsx # 入口文件
│ └── styles.css # 样式文件
├── src-tauri/ # Tauri 后端(Rust)
│ ├── icons/ # 应用图标(各种尺寸)
│ ├── src/ # Rust 源代码
│ │ └── main.rs # Rust 主文件
│ ├── target/ # Rust 编译输出(首次运行后生成)
│ ├── build.rs # 构建脚本
│ ├── Cargo.toml # Rust 依赖配置
│ └── tauri.conf.json # Tauri 配置文件
├── index.html # HTML 入口
├── package.json # Node.js 配置
├── tsconfig.json # TypeScript 配置
└── vite.config.ts # Vite 配置关键文件解析
1. src-tauri/tauri.conf.json - Tauri 配置文件
json
{
"build": {
"beforeDevCommand": "npm run dev", // 开发前运行的命令
"beforeBuildCommand": "npm run build", // 打包前运行的命令
"devPath": "http://localhost:1420", // 开发服务器地址
"distDir": "../dist" // 打包输出目录
},
"package": {
"productName": "my-first-tauri-app", // 应用名称
"version": "0.0.0" // 应用版本
},
"tauri": {
"allowlist": { // API 权限配置
"all": false, // 默认禁用所有 API
"shell": {
"all": false
}
},
"windows": [ // 窗口配置
{
"title": "My First Tauri App", // 窗口标题
"width": 800, // 窗口宽度
"height": 600 // 窗口高度
}
]
}
}2. src-tauri/src/main.rs - Rust 主文件
rust
// Prevents additional console window on Windows in release
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
// 定义一个简单的命令
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet]) // 注册命令
.run(tauri::generate_context!())
.expect("error while running tauri application");
}3. src/App.tsx - React 主组件
tsx
import { useState } from "react";
import { invoke } from "@tauri-apps/api/tauri";
import "./App.css";
function App() {
const [greetMsg, setGreetMsg] = useState("");
const [name, setName] = useState("");
async function greet() {
// 调用 Rust 命令
setGreetMsg(await invoke("greet", { name }));
}
return (
<div className="container">
<h1>Welcome to Tauri!</h1>
<form
onSubmit={(e) => {
e.preventDefault();
greet();
}}
>
<input
onChange={(e) => setName(e.currentTarget.value)}
placeholder="Enter a name..."
/>
<button type="submit">Greet</button>
</form>
<p>{greetMsg}</p>
</div>
);
}
export default App;运行开发服务器
安装依赖
bash
# 安装前端依赖
npm install启动开发模式
bash
npm run tauri dev第一次运行会发生什么?
bash
1. 🔧 编译 Rust 后端
- 下载 Rust 依赖(可能几百个 crate)
- 编译所有依赖
- 这一步可能需要 5-10 分钟(仅第一次)
2. 🚀 启动前端开发服务器
- Vite 启动,通常很快
3. 🎉 打开应用窗口
- 如果一切顺利,会看到应用窗口期望结果:
Compiling tauri v1.5.4
Compiling my-first-tauri-app v0.0.0
Finished dev [unoptimized + debuginfo] target(s) in 2.34s
VITE v5.0.8 ready in 234 ms
➜ Local: http://localhost:1420/
➜ press h to show help然后,应用窗口会自动打开!
测试功能
- 在输入框中输入你的名字
- 点击 "Greet" 按钮
- 你会看到来自 Rust 的问候消息
🎉 恭喜!你的第一个 Tauri 应用已经运行起来了!
添加自定义功能
现在让我们添加一些实用的功能,深入了解 Tauri 的工作原理。
功能一:读取系统信息
1. 修改 Rust 代码
编辑 src-tauri/src/main.rs:
rust
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use std::env;
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
// 新增:获取系统信息
#[tauri::command]
fn get_system_info() -> String {
let os = env::consts::OS;
let arch = env::consts::ARCH;
let family = env::consts::FAMILY;
format!(
"操作系统: {}\n架构: {}\n系统家族: {}",
os, arch, family
)
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
greet,
get_system_info // 注册新命令
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}2. 修改前端代码
编辑 src/App.tsx:
tsx
import { useState } from "react";
import { invoke } from "@tauri-apps/api/tauri";
import "./App.css";
function App() {
const [greetMsg, setGreetMsg] = useState("");
const [name, setName] = useState("");
const [systemInfo, setSystemInfo] = useState("");
async function greet() {
setGreetMsg(await invoke("greet", { name }));
}
// 新增:获取系统信息
async function getSystemInfo() {
const info = await invoke<string>("get_system_info");
setSystemInfo(info);
}
return (
<div className="container">
<h1>Welcome to Tauri!</h1>
{/* 原有的问候功能 */}
<div className="section">
<h2>Greet</h2>
<form
onSubmit={(e) => {
e.preventDefault();
greet();
}}
>
<input
onChange={(e) => setName(e.currentTarget.value)}
placeholder="Enter a name..."
/>
<button type="submit">Greet</button>
</form>
{greetMsg && <p className="result">{greetMsg}</p>}
</div>
{/* 新增:系统信息 */}
<div className="section">
<h2>System Info</h2>
<button onClick={getSystemInfo}>
Get System Info
</button>
{systemInfo && (
<pre className="result">{systemInfo}</pre>
)}
</div>
</div>
);
}
export default App;3. 添加样式
编辑 src/App.css:
css
.container {
margin: 0;
padding: 20px;
display: flex;
flex-direction: column;
gap: 30px;
}
.section {
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 20px;
background: #f9f9f9;
}
.section h2 {
margin-top: 0;
color: #333;
}
input {
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
margin-right: 10px;
font-size: 14px;
}
button {
padding: 10px 20px;
background: #0070f3;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
button:hover {
background: #0051cc;
}
.result {
margin-top: 15px;
padding: 15px;
background: white;
border-radius: 4px;
border-left: 3px solid #0070f3;
}
pre.result {
white-space: pre-wrap;
font-family: monospace;
font-size: 13px;
}保存文件后,应用会自动重新加载(热重载)!
功能二:文件选择和读取
1. 配置权限
编辑 src-tauri/tauri.conf.json:
json
{
"tauri": {
"allowlist": {
"all": false,
"fs": {
"all": false,
"readFile": true,
"scope": ["$DESKTOP/*", "$DOCUMENT/*", "$DOWNLOAD/*"]
},
"dialog": {
"all": false,
"open": true
}
}
}
}2. 添加前端功能
编辑 src/App.tsx,添加文件选择功能:
tsx
import { useState } from "react";
import { invoke } from "@tauri-apps/api/tauri";
import { open } from "@tauri-apps/api/dialog";
import { readTextFile } from "@tauri-apps/api/fs";
import "./App.css";
function App() {
const [greetMsg, setGreetMsg] = useState("");
const [name, setName] = useState("");
const [systemInfo, setSystemInfo] = useState("");
const [fileContent, setFileContent] = useState("");
async function greet() {
setGreetMsg(await invoke("greet", { name }));
}
async function getSystemInfo() {
const info = await invoke<string>("get_system_info");
setSystemInfo(info);
}
// 新增:选择并读取文件
async function selectAndReadFile() {
try {
// 打开文件选择对话框
const selected = await open({
multiple: false,
filters: [{
name: 'Text',
extensions: ['txt', 'md', 'json', 'js', 'ts', 'jsx', 'tsx']
}]
});
if (selected) {
// 读取文件内容
const content = await readTextFile(selected as string);
setFileContent(content);
}
} catch (error) {
setFileContent(`Error: ${error}`);
}
}
return (
<div className="container">
<h1>Welcome to Tauri!</h1>
<div className="section">
<h2>Greet</h2>
<form
onSubmit={(e) => {
e.preventDefault();
greet();
}}
>
<input
onChange={(e) => setName(e.currentTarget.value)}
placeholder="Enter a name..."
/>
<button type="submit">Greet</button>
</form>
{greetMsg && <p className="result">{greetMsg}</p>}
</div>
<div className="section">
<h2>System Info</h2>
<button onClick={getSystemInfo}>
Get System Info
</button>
{systemInfo && (
<pre className="result">{systemInfo}</pre>
)}
</div>
{/* 新增:文件读取 */}
<div className="section">
<h2>File Reader</h2>
<button onClick={selectAndReadFile}>
Select and Read File
</button>
{fileContent && (
<pre className="result file-content">{fileContent}</pre>
)}
</div>
</div>
);
}
export default App;3. 添加文件内容样式
在 src/App.css 中添加:
css
.file-content {
max-height: 300px;
overflow-y: auto;
font-size: 12px;
line-height: 1.5;
}构建生产版本
开发完成后,让我们构建生产版本:
bash
npm run tauri build构建过程:
bash
1. 🔨 构建前端
- 运行 npm run build
- 生成优化后的静态文件
2. 🦀 构建 Rust 后端
- Release 模式编译(启用所有优化)
- 这一步可能需要 5-10 分钟
3. 📦 打包应用
- 生成安装包
- 位置:src-tauri/target/release/bundle/输出结果:
Windows:
- .msi 安装包
- .exe 便携版
macOS:
- .dmg 安装包
- .app 应用包
Linux:
- .deb(Debian/Ubuntu)
- .rpm(Fedora/RHEL)
- .AppImage(通用)体积对比
让我们看看构建结果:
bash
# Tauri 应用
Windows (.msi): ~5-8 MB
macOS (.dmg): ~6-10 MB
Linux (.deb): ~5-8 MB
# 对比 Electron(相同功能)
Windows: ~150 MB
macOS: ~200 MB
Linux: ~120 MB
# 体积差距:约 20-30 倍!调试技巧
前端调试
bash
# 开发模式会自动打开 DevTools
npm run tauri dev
# 或者在应用窗口中:
- Windows/Linux: F12 或 Ctrl+Shift+I
- macOS: Cmd+Option+I后端调试
rust
// 在 Rust 代码中添加日志
#[tauri::command]
fn greet(name: &str) -> String {
println!("Greet command called with name: {}", name);
format!("Hello, {}!", name)
}
// 查看日志输出在运行 tauri dev 的终端常见问题排查
问题 1:命令未定义
bash
错误信息:
command greet not found解决方案:
rust
// 确保命令已注册
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
greet, // ✅ 必须在这里注册
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}问题 2:API 权限被拒绝
bash
错误信息:
api not allowed: fs.readFile解决方案:
json
// 在 tauri.conf.json 中启用 API
{
"tauri": {
"allowlist": {
"fs": {
"readFile": true // ✅ 必须明确启用
}
}
}
}问题 3:热重载不工作
bash
# 检查前端开发服务器
- 确认 Vite 正在运行
- 检查 devPath 配置是否正确
# Rust 代码修改需要重新编译
- 保存 .rs 文件后会自动重新编译
- 如果没有,尝试重启 tauri dev最佳实践建议
1. 项目组织
推荐的目录结构:
src/
├── components/ # React 组件
├── hooks/ # 自定义 hooks
├── utils/ # 工具函数
└── tauri-api/ # Tauri API 封装
src-tauri/src/
├── commands/ # 命令实现
├── utils/ # Rust 工具函数
└── main.rs # 主文件2. 错误处理
rust
// Rust 端
#[tauri::command]
fn my_command() -> Result<String, String> {
match some_operation() {
Ok(result) => Ok(result),
Err(e) => Err(e.to_string())
}
}
// TypeScript 端
try {
const result = await invoke('my_command');
} catch (error) {
console.error('Command failed:', error);
}3. 类型安全
typescript
// 定义命令参数和返回类型
interface GreetParams {
name: string;
}
async function greet(name: string): Promise<string> {
return await invoke<string>('greet', { name });
}总结
🎉 恭喜你完成了第一个 Tauri 应用!让我们回顾一下学到的内容:
✅ 核心知识点
项目创建
- 使用
create-tauri-app脚手架 - 选择合适的前端框架
- 理解项目结构
- 使用
前后端通信
- Rust 端定义命令(
#[tauri::command]) - 前端调用命令(
invoke) - 参数传递和返回值处理
- Rust 端定义命令(
API 使用
- 文件系统操作
- 对话框
- 系统信息
开发流程
- 开发模式(
tauri dev) - 热重载
- 调试技巧
- 开发模式(
构建打包
- 生产构建(
tauri build) - 多平台打包
- 体积优化
- 生产构建(
🚀 下一步学习
现在你已经掌握了 Tauri 的基础,可以:
- 深入学习 Tauri 的核心概念
- 了解窗口管理
- 学习更多系统 API
- 构建实际项目
💡 学习建议
多动手实践
- 修改示例代码
- 尝试不同的 API
- 解决遇到的问题
阅读官方文档
- API 文档很全面
- 有很多实用示例
- 社区很活跃
参考优秀项目
- GitHub 上搜索 Tauri
- 学习项目结构
- 了解最佳实践
下一篇文章,我们将深入探讨 Tauri 的核心概念,包括架构设计、安全模型、配置系统等。
相关文章推荐:
有问题欢迎留言讨论,我会及时解答!
完整代码仓库:
参考资源: