桌面客户端交付实录:Tauri 2 的体积、冷启动与进程管理实测
为什么不用 Electron
需求很简单:一个已经在网页上跑得好好的产品,想要一个桌面客户端——能双击打开、能常驻托盘、能自己更新。
第一反应是 Electron,我先把对照实测做了:
| 对照项 | Electron | Tauri 2(本项目) |
|---|---|---|
| 运行时体积 | 368 MB(实测) | 随包不携带浏览器(用系统 WebView2) |
| 首屏时间 | 3017 ms(实测) | 冷启动中位 608 ms |
| 交付包 | 体积大 | 7.93 MB(绿色 zip) |
差了将近 50 倍。所以我选了 Tauri 2,代价也说清楚:Windows 上依赖 WebView2、Rust 侧调试成本更高、生态比 Electron 小。**这些代价换来的是”用户下载 8 MB 而不是 300 MB”**,对我要交付的场景是划算的。
架构:壳只做两件事
最重要的一条设计决定:这个外壳里没有一行业务逻辑。它只做两件事——进程管理和呈现。
1 | ┌──────────────────────────────────────────┐ |
配置层面就三行是关键:
1 | { |
复用现有产物这件事值得强调:产品的前端已经在迭代了,桌面端不该再造一份。壳加载的就是同一份 web/dist,前端同学改完照常构建,桌面端自动跟上——没有第二份代码需要同步。
验收:四个探针,不靠手感
“能打开、能跑”不是验收。我定了四个可量化的探针,结果写进证据 JSON:
| 探针 | 结果 | 阈值 / 对照 |
|---|---|---|
| 交付包体积 | 8,319,551 B ≈ 7.93 MB | 对照 Electron 368 MB |
| 冷启动(n=5) | min 599 / 中位 608 / max 642 ms | 阈值 3000 ms ✅ |
| sidecar 可执行性 | 壳与 sidecar 同目录,current_exe() 父目录定位,只调无害子命令自证通道 |
✅ |
| 停止 20 次 | 优雅停止 20/20、硬杀 0、孤儿进程 0、命令行许可泄漏 0,总耗时 55,089 ms | 阈值 ≥19 次、孤儿必须 0 ✅ |
两个容易被忽略的点:
- 孤儿进程 0:桌面壳最常见的脏问题是”关窗口了,后台进程还在”。我特地统计了停止后是否残留子进程——0 才是通过。
- 命令行泄漏 0:许可/密钥这类敏感数据绝不能出现在进程命令行里(
ps一抓就有)。所以壳启动 sidecar 时只传无害参数,许可走别的通道。
踩过的六个坑
- Windows 优雅停止:直接杀进程会让 sidecar 来不及收尾。正确做法是发
CTRL_C_EVENT(配隐藏控制台),让它自己走完退出流程——这也是”20/20 优雅退出”的前提。 - **CSP 要放行
unsafe-eval**:现代前端框架(含某些模板/图表库)在严格 CSP 下会直接白屏。Tauri 默认 CSP 很严,需要显式放行,否则你会在”本地能跑、打包白屏”上耗一晚上。 - sidecar 命名必须带 target triple:
externalBin找的是runner-x86_64-pc-windows-msvc.exe这种带平台后缀的文件名,名字不对就是”打不出包”。 - 第一版不买签名证书:代码签名证书一年 ¥1000–3000,内测阶段不划算。代价是 SmartScreen 会拦——我的做法是发绿色 zip,附一页图文”解除锁定”步骤,把用户操作降到三步以内。
- 自动更新要验签:内置 minisign 公钥,更新包签名不对就不装;更新源指向自家接口。这里有个必须在发布前修掉的债:内测期走 http,需要打开 Tauri 的”允许不安全传输”开关——发正式版前必须切 https 并关掉它。
- **错误提示不能落”未知错误”**:这是产品级要求。用户看到”未知错误”只会卸载;能自己解释的错误必须写清是什么、为什么、怎么办。
一点体会
桌面端的难点不在 Rust,也不在打包,而在边界:
- 壳与业务的边界(壳里不放业务逻辑);
- 进程与进程的边界(谁启动谁、谁负责收尾、敏感信息走哪条路);
- 内测与发布的边界(哪些是为省事临时开的开关,必须在发布前关掉)。
把这三条边界写清楚,剩下的就是”探针驱动”的重复劳动了——能报出数字,才算交付完成。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 须臾的博客!