Tauri 2.x 教程系列 (一):Hello Tauri — 从零搭建第一个桌面应用

Tauri 2.x 教程系列 (一):Hello Tauri --- 从零搭建第一个桌面应用

前言

Tauri 是一个轻量级的桌面应用框架,使用 Rust 作为后端,Web 技术(React/Vue/Svelte)作为前端。相比 Electron,Tauri 打包体积更小(通常 <10MB)、内存占用更低、安全性更好。

本教程使用 Tauri 2.x + React + TypeScript,从零开始搭建第一个桌面应用。

📦 本系列完整代码:https://gitee.com/futurelei/rs-tauri-demo

💡 本系列所有项目配置了 Cargo Workspace,8 个项目共享编译缓存,避免重复编译。

环境准备

1. 安装系统依赖 (Ubuntu)

bash 复制代码
sudo apt-get update
sudo apt-get install -y \
  libwebkit2gtk-4.1-dev \
  libsoup-3.0-dev \
  libjavascriptcoregtk-4.1-dev \
  build-essential \
  curl wget file \
  libxdo-dev libssl-dev \
  libayatana-appindicator3-dev \
  librsvg2-dev

2. 安装 Rust

bash 复制代码
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

3. 安装 Tauri CLI

bash 复制代码
cargo install tauri-cli --version "^2"

4. 验证安装

bash 复制代码
rustc --version   # rustc 1.xx.x
cargo tauri --version  # tauri-cli 2.xx.x

创建项目

方式一:使用 create-tauri-app(推荐)

bash 复制代码
npm create tauri-app@latest
# 选择: React + TypeScript + Vite

方式二:手动搭建(本教程采用)

我们手动创建以理解每个文件的作用:

复制代码
01-hello-tauri/
├── index.html              # Vite 入口 HTML
├── package.json            # 前端依赖
├── vite.config.ts          # Vite 配置
├── tsconfig.json           # TypeScript 配置
├── src/
│   ├── main.tsx            # React 入口
│   └── App.tsx             # 主组件
├── src-tauri/
│   ├── Cargo.toml          # Rust 依赖(Workspace member)
│   ├── build.rs            # Tauri 构建脚本
│   ├── tauri.conf.json     # Tauri 配置
│   ├── capabilities/       # 权限配置
│   │   └── default.json
│   └── src/
│       ├── main.rs         # 程序入口
│       └── lib.rs          # 应用核心

💡 本系列在根目录配置了 Cargo WorkspaceCargo.toml),8 个项目的 Rust 代码共享一个 target/ 编译目录,避免每个项目独立编译占用 3-4GB 磁盘。

编写代码

package.json

json 复制代码
{
  "name": "01-hello-tauri",
  "private": true,
  "version": "0.1.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "tauri": "tauri"
  },
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "@tauri-apps/api": "^2"
  },
  "devDependencies": {
    "@tauri-apps/cli": "^2",
    "@types/react": "^18.3.12",
    "@types/react-dom": "^18.3.1",
    "@vitejs/plugin-react": "^4.3.4",
    "typescript": "^5.6.3",
    "vite": "^6.0.0"
  }
}

Vite 配置

typescript 复制代码
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  clearScreen: false,
  server: {
    port: 1420,          // Tauri 固定端口
    strictPort: true,
    watch: {
      ignored: ["**/src-tauri/**"],  // 不监听 Rust 文件
    },
  },
});

Rust 后端 --- 核心逻辑 (lib.rs)

rust 复制代码
// src-tauri/src/lib.rs

/// 获取问候语
fn greet(name: String) -> String {
    let display_name = if name.trim().is_empty() {
        "World".to_string()
    } else {
        name
    };
    format!("你好, {}! 欢迎来到 Tauri 2.x!", display_name)
}

/// Tauri 命令:根据 name 返回问候语
#[tauri::command]
fn greet_command(name: String) -> String {
    greet(name)
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![greet_command])
        .run(tauri::generate_context!())
        .expect("启动应用时出错");
}

TDD: 先写测试

rust 复制代码
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_greet_with_name() {
        let result = greet("Alice".to_string());
        assert_eq!(result, "你好, Alice! 欢迎来到 Tauri 2.x!");
    }

    #[test]
    fn test_greet_with_empty_name_defaults_to_world() {
        let result = greet("".to_string());
        assert_eq!(result, "你好, World! 欢迎来到 Tauri 2.x!");
    }
}

前端调用

tsx 复制代码
// src/App.tsx
import { useState } from "react";
import { invoke } from "@tauri-apps/api/core";

function App() {
  const [name, setName] = useState("");
  const [greeting, setGreeting] = useState("");

  const handleGreet = async () => {
    const result = await invoke<string>("greet", { name: name || "World" });
    setGreeting(result);
  };

  return (
    <main>
      <h1>👋 Hello Tauri 2.x</h1>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
        onKeyDown={(e) => e.key === "Enter" && handleGreet()}
      />
      <button onClick={handleGreet}>问候</button>
      {greeting && <p>✨ {greeting}</p>}
    </main>
  );
}

tauri.conf.json

json 复制代码
{
  "productName": "Hello Tauri",
  "version": "0.1.0",
  "identifier": "com.tauri-tutorial.hello-tauri",
  "build": {
    "frontendDist": "../dist",
    "devUrl": "http://localhost:1420",
    "beforeDevCommand": "npm run dev",
    "beforeBuildCommand": "npm run build"
  },
  "app": {
    "windows": [{
      "title": "01 - Hello Tauri",
      "width": 800,
      "height": 600,
      "center": true
    }],
    "security": { "csp": null }
  }
}

运行项目

bash 复制代码
cd 01-hello-tauri
npm install
npm run tauri dev             # 启动开发模式(自动编译 Rust)

首次运行会编译 Rust 代码,耗时约 2-5 分钟。之后会看到 Tauri 窗口打开,显示我们的 React 应用。

运行测试

bash 复制代码
# 方式一:从项目目录(推荐初学者)
cd 01-hello-tauri/src-tauri
cargo test

# 方式二:从根目录使用 workspace
cargo test -p hello-tauri

💡 Workspace 提示 :本系列所有项目共享编译缓存,从根目录执行 cargo test -p <package名> 或从子目录执行 cargo test 都使用同一份 target/

Tauri 2.x 关键概念

1. 项目结构

目录/文件 作用
src/ React 前端代码
src-tauri/src/ Rust 后端代码
src-tauri/tauri.conf.json 应用配置(窗口、权限、打包)
src-tauri/capabilities/ 权限声明(2.x 新增)
src-tauri/Cargo.toml Rust 依赖管理

2. 命令系统 (IPC)

Tauri 的核心通信机制:前端通过 invoke() 调用 Rust 函数。

复制代码
前端 invoke("greet", { name: "Alice" })
  → Rust #[tauri::command] fn greet_command(name: String) -> String
  → 返回结果到前端

3. 权限模型 (Capabilities)

Tauri 2.x 引入了声明式权限系统,在 capabilities/default.json 中声明:

json 复制代码
{
  "identifier": "default",
  "windows": ["main"],
  "permissions": ["core:default"]
}

常见问题

Q: 编译时 icon 文件缺失?

A: 在 src-tauri/icons/ 中放置 32x32.png、128x128.png 等图标文件。

Q: 端口被占用?

A: vite.config.ts 中的 port 改为其他值,同时更新 tauri.conf.json 的 devUrl。

Q: 8 个项目磁盘占用太大?

A: 根目录的 Cargo Workspace 已自动共享 target/ 目录,8 个项目共用一份编译产物。

总结

本节我们完成了:

  • ✅ Tauri 2.x 环境搭建
  • ✅ 理解项目结构
  • ✅ 第一个 Tauri 命令 (greet)
  • ✅ 前端调用后端
  • ✅ TDD: Rust 单元测试
  • ✅ 应用运行与调试
  • ✅ Cargo Workspace 共享编译

下一节,我们将深入 React 组件化开发与 Tauri 命令系统进阶。


本系列文章:

  • (一) Hello Tauri --- 从零搭建第一个桌面应用 👈
  • (二) React 组件化与 Tauri 命令系统
  • (三) 状态管理:Tauri State + Zustand + 事件
  • (四) SQLite 本地数据库持久化
  • (五) 路由导航与多页面架构
  • (六) 测试金字塔与 TDD 实践
  • (七) 大型项目工程化规范
  • (八) 综合项目实战:Todo 应用
相关推荐
smallswan1 小时前
第十七 位运算
rust
a诠释淡然21 小时前
C++ vs Rust:哪个更适合你的下一个项目?
开发语言·c++·rust
Vallelonga1 天前
Rust 生命周期标注积累
开发语言·rust
星栈1 天前
Makepad UI 代码怎么读:别被语法吓住
前端·rust
MageGojo1 天前
基于 Rust + Headless Chrome 的自动化文章发布系统设计与登录态持久化实现
自动化测试·rust·桌面应用·headless-chrome·gpui
特立独行的猫a1 天前
Tauri Demo 移植到鸿蒙PC上的交叉编译全流程实战总结
华为·rust·harmonyos·tauri·鸿蒙pc
星栈独行1 天前
10 分钟跑起第一个 Makepad 应用:先把窗口开起来
前端·程序人生·ui·rust·开源·github
星空椰1 天前
Tauri 开发模式下 SQLite 数据库文件变更导致应用自动重启问题
数据库·sqlite·tauri
古城小栈1 天前
langchainrust:构建一个高效智能体
ai·rust