使用 Rust 与 Tauri 构建跨平台 GUI 应用:指南

更新于 2026-01-18

codezup 2025-05-10

1. 引言

1.1 Rust 与 Tauri 跨平台 GUI 应用概述

在当今时代,应用程序被期望能够无缝运行于多个平台之上,开发者不断寻求能够“一次编写、到处部署”的工具。Rust 凭借其对安全性和性能的高度重视,已成为系统编程领域极具吸引力的选择。然而,使用 Rust 构建图形用户界面(GUI)应用程序并不像使用 JavaScript 或 Python 等语言那样直接。此时,Tauri 框架应运而生——它允许开发者利用 HTML、CSS 和 JavaScript 等 Web 技术构建跨平台桌面应用,同时使用 Rust 处理后端逻辑。

1.2 学习目标与先决条件

本指南将引导你创建一个基于 Rust 和 Tauri 的基础跨平台 GUI 应用程序,涵盖核心概念、具体实现以及最佳实践。完成本指南后,你将能够:

  • 设置一个 Tauri 项目
  • 实现一个基础的 CRUD(增删改查)应用程序
  • 处理前端与后端之间的通信
  • 在 Windows、macOS 和 Linux 上部署该应用程序

先决条件包括对 Rust 和 JavaScript 的基本了解,并已在系统中安装 Rust 和 Node.js。此外,Tauri 还需要 Git 来下载项目模板。

1.3 工具与资源

  • Rust 编程语言
  • Tauri 框架
  • Svelte

2. 技术背景

2.1 核心概念与术语

  • Tauri:一个使用 Web 技术构建跨平台桌面应用的框架。
  • Webview:在原生窗口中渲染 Web 内容。
  • Rust 命令(Commands):处理后端逻辑,由前端调用。

2.2 内部原理

Tauri 的架构包含一个原生外壳(native shell)和一个 Webview,两者通过 WebSocket 或 HTTP 进行通信。Rust 命令运行在独立进程中,从而实现安全高效的后端操作。

2.3 最佳实践与常见陷阱

  • 惯用 Rust:充分利用 Rust 的并发模型。
  • 异步编程:避免阻塞操作。
  • Web 最佳实践:针对桌面环境进行优化。

3. 实现指南

3.1 分步设置

安装 Rust 和 Tauri CLI

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
npm install -g @tauri-apps/cli

创建新项目

npx tauri new tauri_rust_demo
cd tauri_rust_demo

选择 Svelte 及附加功能

3.2 基础应用开发

修改 src/main.rs 以添加一个命令:

#[command]
fn greet(name: String) -> String {
    format!("Hello, {}!", name)
}

src/App.svelte 中添加一个按钮来测试该命令:

<script>
  async function greetName() {
    const response = await invoke('greet', { name: 'World' });
    alert(response);
  }
</script>

<button on:click={greetName}>Greet</button>

3.3 高级功能:CRUD 操作

添加一个用于处理笔记的命令:

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Note {
    id: i32,
    content: String,
}

#[command]
fn get_notes() -> Vec<Note> {
    vec![Note { id: 1, content: "First note".to_string() }]
}

修改 src/App.svelte 以显示笔记:

<script>
  let notes = [];

  async function loadNotes() {
    const response = await invoke('get_notes');
    notes = response;
  }

  async function addNote() {
    const newNote = "New note";
    const response = await invoke('add_note', { content: newNote });
    notes.push(response);
  }
</script>

{#if notes.length === 0}
  <p>No notes yet!</p>
{:else}
  <ul>
    {#each notes as note}
      <li>{note.content}</li>
    {/each}
  </ul>
{/if}
<button on:click={addNote}>Add Note</button>

4. 代码示例

4.1 功能测试

测试添加笔记并检查列表:

#[test]
fn test_add_note() {
    let note = Note { id: 2, content: "Test note".to_string() };
    assert_eq!(note.content, "Test note");
}

4.2 错误处理

优雅地处理命令错误:

#[command]
fn get_notes() -> Result<Vec<Note>, String> {
    Ok(vec![Note { id: 1, content: "First note".to_string() }])
}

4.3 包含边界情况的完整示例

包含加载状态和错误消息:

<script>
  let notes = [];
  let isLoading = false;
  let error = null;

  async function loadNotes() {
    isLoading = true;
    error = null;
    try {
      const response = await invoke('get_notes');
      notes = response;
    } catch (e) {
      error = e.message;
    } finally {
      isLoading = false;
    }
  }
</script>

{#if isLoading}
  <div>Loading...</div>
{:else if error}
  <div class="error">{error}</div>
{:else if notes.length === 0}
  <p>No notes yet!</p>
{:else}
  <ul>
    {#each notes as note}
      <li>{note.content}</li>
    {/each}
  </ul>
{/if}

5. 最佳实践与优化

5.1 性能

在 Rust 命令中使用 async/await 进行优化:

#[command]
async fn fetch_data(url: &str) -> Result<String, String> {
    let response = reqwest::get(url).await?;
    Ok(response.text().await?)
}

5.2 安全性

对输入进行清理并使用 HTTPS:

use xiuo::Takeover;

#[command]
fn process_input(input: &str) -> String {
    let clean = input.trim().to_string();
    // 根据需要进一步清理
    clean
}

5.3 代码组织

合理组织项目结构:

src/
├── commands/
│   ├── mod.rs
│   └── note_commands.rs
├── models/
│   └── note.rs
├── error.rs
└── main.rs

5.4 常见错误

避免阻塞操作:

// 不良实践
#[command]
fn blocking_operation() {
    std::thread::sleep(std::time::Duration::from_secs(10));
}

// 良好实践
#[command]
async fn non_blocking_operation() {
    tokio::task::spawn(async {
        tokio::time::sleep(std::time::Duration::from_secs(10)).await;
    });
}

6. 测试与调试

6.1 命令测试

为命令编写单元测试:

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_get_notes() {
        let notes = get_notes().unwrap();
        assert!(!notes.is_empty());
    }
}

6.2 调试

使用 Tauri 内置工具:

cargo watch -x run

6.3 常见问题

通过配置 tauri.conf.json 解决 CORS 问题:

"allowed_origins": ["*"],
"allowlist": {
  "cors": {
    "all": ["*"]
  }
}

7. 结论

7.1 总结

你已成功使用 Rust 和 Tauri 构建了一个跨平台 GUI 应用,涵盖了项目设置、功能实现以及最佳实践。

7.2 后续步骤

探索 Tauri 的高级特性,并进一步深化你的 Rust 知识。

7.3 附加资源

本指南为你构建高效、安全且响应迅速的跨平台应用程序奠定了坚实基础。祝你编码愉快!