1. 为什么选择Tauri 2.0重构桌面应用
去年用Electron开发的股票盯盘工具安装包膨胀到120MB后,我开始寻找更轻量的解决方案。直到遇见Tauri 2.0这个基于Rust的桌面应用框架,最终产出的应用安装包仅5.3MB,内存占用从Electron版的300MB降至35MB。这种量级的性能提升,让我决定把整个技术选型过程记录下来。
传统Electron应用之所以体积庞大,是因为每个应用都内置了完整的Chromium浏览器内核。而Tauri采用操作系统自带的WebView作为渲染引擎,后端用Rust编写,这种架构差异直接带来了数量级的体积优化。最新发布的Tauri 2.0在1.0基础上强化了跨平台支持,现在可以稳定生成Windows、macOS和Linux三端应用。
2. 开发环境准备与项目初始化
2.1 Rust工具链配置
首先需要安装Rust编译环境,这是Tauri的后端基础。推荐使用rustup工具管理版本:
bash复制curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
rustup target add wasm32-unknown-unknown
安装完成后运行rustc --version验证,当前稳定版(1.70.0+)均可正常工作。特别要注意的是,在Windows平台需要额外安装Microsoft Visual Studio C++生成工具。
2.2 前端框架选型
虽然Tauri支持任意前端框架,但考虑到性能与生态,我选择Vue 3组合式API+TypeScript方案:
bash复制npm init vue@latest tauri-stock
cd tauri-stock
npm install @tauri-apps/api@latest
项目结构保持标准Vue布局即可,Tauri会在编译时自动处理前端资源。为提升开发体验,建议配置Vite的HMR热更新:
javascript复制// vite.config.ts
export default defineConfig({
plugins: [vue(), tauri({
hotReload: true
})]
})
2.3 Tauri工程初始化
在Vue项目根目录执行:
bash复制npm install --save-dev @tauri-apps/cli
npm tauri init
初始化过程会生成src-tauri目录,其中tauri.conf.json是核心配置文件。需要特别关注以下参数:
json复制{
"build": {
"distDir": "../dist",
"devPath": "http://localhost:5173",
"beforeDevCommand": "npm run dev",
"beforeBuildCommand": "npm run build"
},
"tauri": {
"bundle": {
"targets": ["msi", "app", "dmg"]
}
}
}
3. 核心功能模块实现
3.1 股票数据获取方案
通过对比多个免费API接口,最终选择阿里云市场的股票行情接口。在Rust后端实现请求逻辑:
rust复制// src-tauri/src/main.rs
use serde_json::Value;
use reqwest::header;
#[tauri::command]
async fn get_stock_data(code: &str) -> Result<Value, String> {
let client = reqwest::Client::new();
let res = client.get("https://ali-stock.showapi.com/real-stockinfo")
.header(header::AUTHORIZATION, "APPCODE your_app_code")
.query(&[("code", code)])
.send()
.await
.map_err(|e| e.to_string())?;
res.json::<Value>().await.map_err(|e| e.to_string())
}
前端通过Tauri的命令系统调用:
typescript复制import { invoke } from '@tauri-apps/api'
const fetchData = async (code: string) => {
const data = await invoke('get_stock_data', { code })
stockList.value = JSON.parse(data as string)
}
3.2 原生通知与托盘图标
利用Tauri的原生能力实现股价提醒:
rust复制// 系统通知
use tauri::Manager;
app.handle().plugin(tauri_plugin_notification::init())?;
// 托盘图标
use tauri::{SystemTray, SystemTrayMenu};
let tray_menu = SystemTrayMenu::new().add_item("退出");
let system_tray = SystemTray::new().with_menu(tray_menu);
tauri::Builder::default()
.system_tray(system_tray)
.on_system_tray_event(|app, event| match event {
SystemTrayEvent::MenuItemClick { id, .. } => {
if id == "quit" { app.exit(0); }
}
_ => {}
});
3.3 本地数据持久化
采用SQLite存储用户自选股列表,通过tauri-plugin-sql插件实现:
toml复制# src-tauri/Cargo.toml
[dependencies]
tauri-plugin-sql = { version = "0.4", features = ["sqlite"] }
前端调用示例:
typescript复制import { execute } from '@tauri-apps/plugin-sql'
await execute(
'CREATE TABLE IF NOT EXISTS stocks (id INTEGER PRIMARY KEY, code TEXT UNIQUE)'
)
4. 性能优化实战技巧
4.1 资源压缩策略
通过实测发现,前端资源经过以下处理可减少40%体积:
- 使用Vite的build配置:
javascript复制build: {
minify: 'terser',
terserOptions: {
compress: {
drop_console: true
}
}
}
- 图片资源转Base64内联:
javascript复制assetsInlineLimit: 4096 // 4KB以下图片转base64
4.2 Rust编译优化
在Cargo.toml中添加以下配置可显著减小二进制体积:
toml复制[profile.release]
lto = true
codegen-units = 1
panic = "abort"
strip = true
4.3 动态加载优化
将不常用的功能模块(如历史数据查看)拆分为独立JS文件:
javascript复制const AnalysisView = defineAsyncComponent(() =>
import('./views/AnalysisView.vue')
)
5. 打包发布与实测数据
5.1 多平台构建配置
在tauri.conf.json中设置平台特定参数:
json复制"windows": {
"certificateThumbprint": "",
"digestAlgorithm": "sha256",
"timestampUrl": "http://timestamp.digicert.com"
},
"macOS": {
"category": "public.app-category.finance",
"minimumSystemVersion": "10.13"
}
构建命令:
bash复制npm run tauri build -- --target universal-apple-darwin # Mac通用二进制
npm run tauri build -- --target x86_64-pc-windows-msi # Windows安装包
5.2 体积与性能对比
| 指标 | Electron版本 | Tauri 2.0版本 |
|---|---|---|
| 安装包大小 | 128MB | 5.3MB |
| 内存占用 | 300MB | 35MB |
| 冷启动时间 | 2.8s | 0.6s |
| CPU占用率(峰值) | 12% | 3% |
实测发现,在低配设备上Tauri版本的优势更加明显。特别是在多窗口场景下,Electron会出现明显卡顿,而Tauri保持流畅。
6. 常见问题解决方案
6.1 跨域请求处理
Tauri默认禁用网络请求,需要在配置中显式声明:
json复制"tauri": {
"allowlist": {
"http": {
"all": true,
"request": true,
"scope": ["https://*.showapi.com/*"]
}
}
}
6.2 原生对话框使用
文件选择等原生操作需要通过Tauri API实现:
typescript复制import { dialog } from '@tauri-apps/api'
const file = await dialog.open({
filters: [{ name: 'CSV', extensions: ['csv'] }]
})
6.3 开发环境热更新问题
当修改Rust代码后,需要重启前端开发服务器才能生效。可以通过以下脚本自动化:
json复制"scripts": {
"dev": "concurrently \"vite\" \"cargo watch -x 'run --features=dev'\""
}
7. 项目架构设计建议
经过多次迭代,总结出以下最佳实践:
-
前后端通信规范:
- 使用
#[tauri::command]宏定义Rust接口 - 前端通过
invoke()统一调用 - 复杂数据结构用serde进行序列化
- 使用
-
错误处理方案:
rust复制#[derive(thiserror::Error, Debug)] enum Error { #[error("Network error: {0}")] Reqwest(#[from] reqwest::Error), #[error("JSON parse error: {0}")] Json(#[from] serde_json::Error) } impl serde::Serialize for Error { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> { serializer.serialize_str(self.to_string().as_ref()) } } -
状态管理策略:
- 简单状态用Pinia管理
- 复杂状态通过Rust后端管理
- 使用Tauri的
state机制共享资源
这个项目让我深刻体会到Rust+Web技术的强大组合。Tauri 2.0目前已经足够稳定用于生产环境,特别是对性能敏感的工具类应用,它能带来质的提升。下一步计划尝试用Tauri开发更多效率工具,把安装包体积控制在10MB以内将成为新的标准线