使用Tauri开发简单桌面程序
Tauri 可以开发主流桌面和移动平台应用程序。使用任何可编译为 HTML、JavaScript 和 CSS 的前端框架来构前端,使用 Rust、Swift 和 Kotlin 等语言进行后端逻辑开发。
https://tauri.app/zh-cn/start/
基本架构
核心组件
- TAO用于跨平台创建应用程序窗口,使用rust实现,是winit的分支。
- WRY跨平台WebView渲染库,使用rust实现,作为抽象层决定使用哪个WebView以及如何交互
- tauri-runtime,tauri与底层WebView库之间的粘合层
- tauri-runtime-wry,为WRY提供系统级交互,例如打印、显示器检测等
- tauri-macros,使用
tauri-codegen为上下文、处理程序和命令创建宏进程模型
每个 Tauri 应用程序都有一个核心进程和多个WebView进程。
核心进程
应用程序的入口点,并且是唯一一个拥有完全操作系统访问权限的组件
创建和协调应用程序窗口、系统托盘菜单或通知
路由所有进程间通信,允许你在一个中心位置拦截、过滤和操作 IPC 消息
负责管理全局状态,例如设置或数据库连接
WebView进程
利用操作系统的WevView库
相当于一个浏览器,执行前端HTML、JavaScript代码
可以通过检查页面元素调试前端页面
进程间通信
Tauri使用异步消息传递进行进程间通信,通信消息有两种:
- 事件:一次性、单向IPC消息,可以由WebView或核心进程发出
- 命令:允许前端通过
invokeAPI调用rust的函数并获取返回数据,命令消息使用类似JSON-RPC协议来序列化请求和响应,所有参数和返回数据必须能序列化为json。
1 | sequenceDiagram |
开发环境
Windows 10(从版本 1803 开始)系统默认支持了WebView2
安装rust
安装nodejs
安装pnpm,使用npm的方式安装
npx pnpm@latest-10 dlx @pnpm/exe@latest-10 setup使用cargo安装
create-tauri-app,这个脚手架工具可以用来引导创建工程cargo install create-tauri-app --locked使用工具创建工程
cargo create-tauri-app根据提示选择工程名称,标识,前端语言,框架等
1
2
3
4
5
6
7➜ /e/dev/rust cargo create-tauri-app
✔ Project name · memory-store
✔ Identifier · memorywalker
✔ Choose which language to use for your frontend · TypeScript / JavaScript - (pnpm, yarn, npm, deno, bun)
✔ Choose your package manager · pnpm
✔ Choose your UI template · Vue - (https://vuejs.org/)
✔ Choose your UI flavor · TypeScript进入新创建的工程目录,执行
pnpm install执行
pnpm tauri dev运行程序
工程结构
默认创建的工程目录如下
1 | ├── .gitignore |
tauri.conf.json是Tauri的主要的配置文件cli工具也会依赖它的位置来找Rust工程目录capabilities/directory is the default folder Tauri reads capability files from (in short, you need to allow commands here to use them in your JavaScript code), to learn more about it, see Securityicons/在tauri.conf.json > bundle > icon下引用,作为应用的图标build.rstauri编译程序src/lib.rs包含Rust 代码和移动端程序入口点#[cfg_attr(mobile, tauri::mobile_entry_point)]), 移动平台上rust代码会编译为库,再被框架使用。src/main.rs桌面程序的入口点,它的main函数中调用lib.rs中的app_lib::run()从而实现和移动端相同的调用流程,后续的代码实现都放在lib.rs中,而不是这个文件。
前端配置
tauri可以看作是一个静态网页服务器,所以需要告诉tauri这些静态网页资源的信息。官方推荐使用vite作为前端框架。
对于根目录中的package.json,确认前端开发和编译配置如下:
1 | "scripts": { |
tauri.conf.json中编译字段的内容配置如下,前端静态资源最终目录为../dist
1 | "build": { |
确保vite.config.ts中的配置服务端口和tauri.conf.json中的端口相同。
模板代码说明
前端调用后端
前端App.vue中,通过输入框调用js的function greet()函数,这个函数通过调用@tauri-apps/api/core的invoke方法给后端发送命令,第一个参数是命令的名称,第二个参数是命令的参数,这里就是输入框中的值。后端函数异步调用返回的结果字串给变量greetMsg,最后页面显示这个结果字串。
1 | <script setup lang="ts"> |
后端capabilities\default.json中permissions字段设置了"core:default"允许前端使用tauri的基本命令。
lib.rs中定义名称为greet的函数,这个函数使用#[tauri::command]属性宏告诉tauri框架这是一个命令处理函数,它接收输入的参数,并返回一个字串结果。在run函数的.invoke_handler中需要把这个greet函数注册,从而让前端的invoke可以调用。
1 | // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ |
实现一个汇率换算程序
前端更改
src目录下新增一个components目录,其中新建Converter.vue组件
1 | <script setup lang="ts"> |
App.vue中引用新增的组件
1 | <script setup lang="ts"> |
后端更改
新建
src-tauri\src\commands目录,并在其中新建convert.rs程序用来处理汇率换算1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70use serde_json::Value;
pub async fn convert_currency(amount: f64, from: String, to: String) -> Result<f64, String> {
// We'll fetch rates using exchangerate-api with base set to `from`
let url = format!("https://api.exchangerate-api.com/v4/latest/{}", from);
// Send GET request
let response = reqwest::get(&url)
.await
.map_err(|e| format!("Failed to fetch exchange rates: {}", e))?;
// Check if response is successful
if !response.status().is_success() {
return Err(format!("Failed to fetch exchange rates. Status: {}", response.status()));
}
// Parse JSON response
let json: Value = response
.json()
.await
.map_err(|e| format!("Failed to parse exchange rates: {}", e))?;
// Use helper to extract rate and compute conversion
compute_converted_amount_from_json(amount, &json, &to)
}
/// Helper: given the parsed JSON (from the exchangerate API) extract the target rate
/// and compute converted amount. This is pure and easy to unit test.
pub fn compute_converted_amount_from_json(
amount: f64,
json: &Value,
to: &str,
) -> Result<f64, String> {
json["rates"][to]
.as_f64()
.map(|rate| amount * rate)
.ok_or_else(|| format!("Failed to extract {} rate from response", to))
}
mod tests {
use super::*;
use serde_json::json;
fn compute_conversion_success() {
let json = json!({
"rates": {
"USD": 2.0,
"CNY": 0.5
}
});
let res = compute_converted_amount_from_json(10.0, &json, "USD").unwrap();
assert!((res - 20.0).abs() < 1e-9);
}
fn compute_conversion_missing_rate() {
let json = json!({
"rates": {
"CNY": 0.5
}
});
let err = compute_converted_amount_from_json(10.0, &json, "USD").unwrap_err();
assert!(err.contains("Failed to extract USD"));
}
}lib.rs中使用新增的模块src-tauri\src\目录中新增commands.rs文件,声明commands目录下的子模块1
2
3pub mod convert;
// Re-export commonly used items
pub use convert::convert_currency;lib.rs中注册新添加的命令1
2
3
4
5
6
7
8
9
10
11pub mod commands;
use commands::{convert_currency, greet};
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_opener::init())
.invoke_handler(tauri::generate_handler![greet, convert_currency])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
新增文件目录结构如下
1 | ├── src |
程序运行

程序打包
执行pnpm tauri build会编译release版本程序,并使用工具打包。
应用程序编译生成可执行程序后,tauri的工具会自动使用wix314和nsis去制作安装包,但是由于这两个工具需要从github下载,会卡住,因此可以提前配置好这两个工具。
分别使用GitHub代理下载 WixTools314和NSIS并将压缩包的内容解压到C:\Users\Edison\AppData\Local\tauri\WixTools314和C:\Users\Edison\AppData\Local\tauri\NSIS目录下。
下载 nsis_tauri_utils.dll到C:\Users\Edison\AppData\Local\tauri\NSIS\Plugins\x86-unicode\additional目录下
这样再执行build就可以直接使用下载好的工具打包,生成的安装包在 \src-tauri\target\release\bundle\目录下,分别是msi和nsis安装包。