之前我把一个本地跑 DeepSeek 的 AI 桌面工具塞进了 Tauri,当时心动的理由特别朴素:官方一句话「安装包只有几 MB」,对比 Electron 动辄上百兆的庞然大物,这账怎么算都该选 Tauri。结果真做完给内测用户用,踩的坑比我看过的所有入门教程加起来都多。这篇文章不是来劝退的,是把那些文档里轻描淡写、真到上线才爆发的点,按我自己的血泪顺序摊开讲。
先泼盆冷水:Tauri 小,但「小」是有代价的
装好打包完我第一反应是开心,主程序确实才几兆。但等我把 llama.cpp 的 sidecar 二进制、加上模型权重一起打进去,安装包直接飙到几个 G。这时候我才反应过来,Tauri 说的「小」指的是运行时壳子小,它可没帮你把模型也瘦身。Electron 那一百多兆里其实包含了完整的 Chromium,而你用 Tauri 省下来的那点体积,在本地大模型场景里基本被 sidecar 吃回去了。
所以别拿「体积小」当唯一决策依据。真正该问的是:你的应用到底要不要带重资源?如果只是个调远程 API 的轻客户端,Tauri 的体积优势实实在在;但只要涉及本地推理、本地数据库、本地大文件,这个优势就会迅速缩水。
坑一:系统 WebView 碎片化,UI 会在别人机器上「长歪」
Tauri 不打包浏览器,它复用系统自带的 WebView:Windows 上是 WebView2(本质是 Chromium 内核),macOS 是 WKWebView,Linux 是 webkit2gtk。听起来省事,代价是你永远不知道用户机器上的 WebView 是哪个版本。
我有个内测用户是 Win10 老版本,WebView2 还是系统自带的旧版。我本地 Mac 上完美的一处 flex 布局,到他那儿文字直接溢出换行错乱。查了半天才发现是某个 CSS 特性在那个 WebView 版本里支持不全。Electron 反而没这问题,因为它自带锁版本 Chromium,所有人渲染一致。
教训很具体:别一上来就无脑用最新的 CSS 语法。打包前至少在 Windows、macOS 各找一台「非最新系统」的机器过一遍,或者干脆把 WebView2 运行时作为前置依赖打进安装包,别依赖用户自己有。
坑二:前端和 Rust 之间通信,不是一次免费的函数调用
Tauri 的设计是前端发 invoke 给 Rust 侧处理,再拿返回值。文档示例里都是「点按钮、弹个问候」这种轻量交互,看起来跟调个 fetch 差不多。但实际跑本地模型流式输出时,这个模型就不够用了。
两个真实问题:一是 invoke 是请求-响应模型,一次调用拿到一个完整结果,可大模型是 token 一个一个吐出来的,你不可能等它生成完再一次性返回;二是前后端之间走的是 JSON 序列化,我要是把模型每帧生成的大块二进制往回传,序列化开销能直接把界面卡死。
正确的做法是用 Tauri 的 event 机制:Rust 侧拿到模型流式的 token,就通过 emit 主动往前端的事件通道推,前端监听后增量渲染。这跟「前端主动问、后端答」的思维方式不一样,得把交互重构成「后端主动推、前端订阅」。我一开始按 invoke 思路写,卡了两天才转过弯。
坑三:本地跑模型这事儿,Tauri 一点忙没帮上
这是我之前最大的误判。我以为选了 Tauri 就等于「有了桌面 AI 能力」,其实 Tauri 只是个壳,模型推理得我自己接。具体来说,我得在 Rust 侧用 Command 拉起本地的 llama.cpp 或 Ollama 进程当 sidecar,然后去读它的 stdout 拿流式 token,再转成 Tauri event 喂给前端。
也就是说,进程生命周期管理、GPU 参数透传、stdout 流解析、崩溃重启,这些真正的工作量全得我自己写。Tauri 提供的是「能拉起子进程、能发事件」这种底层积木,不是「帮你跑模型」的成品。要是有人跟你说「用 Tauri 做 AI 桌面应用很省事」,他八成只写了个壳,模型那摊子还没碰。
坑四:签名和公证,比写功能代码还磨人
功能写完只是开始。macOS 上你的应用要上架,甚至只是想让用户双击能打开,都得走 Apple 的公证(notarization),要开发者账号、要 codesign、要传包给苹果扫一遍。Windows 上想去掉「未知发布者」的红色警告,得买代码签名证书,一年小几千块。
这块 Tauri 文档有写,但都藏在「分发」章节末尾,语气轻描淡写。真做的时候每一步都可能卡你半天:entitlement(权限描述文件)配错,公证被打回;证书链不完整,双击仍报警。我个人的体会是,桌面应用 30% 的精力在写功能,40% 在搞打包签名,剩下 30% 在修前面两块的连锁问题。Electron 这边生态成熟些,社区踩坑记录也多,反而好搜。
坑五:自动更新得自己搭,别想开箱即用
Tauri 带 updater 插件,但前提是你得有个能托管签名更新包的服务器,而且更新包必须用自己的密钥签名,否则客户端拒更。这意味着你得单独维护一套更新分发链路。对比 electron-updater,它对接 GitHub Release 几乎零配置,Tauri 这边的心智负担明显更重。如果你的产品要长期迭代、用户量上来后靠手动发安装包,这坑会越来越大。
那什么时候我还是会选 Tauri
愿意碰 Rust、且真的在意安装包体积和安全模型(Rust 侧能做更细的权限收口)的时候,Tauri 很香。它逼你把「前端能干什么」和「系统能干什么」划清边界,这种克制对长期维护是好事。
反过来,如果你的团队全是 JS、要的是「界面在每个用户机器上长得一模一样」、或者根本不想碰签名公证这些脏活,Electron 依然是更稳的选择。它重,但重得省心。
我做 HarnessDesk 选 Tauri,是因为它本质是「轻壳 + 本地大模型」,体积和安全边界对我重要,我也啃得动 Rust。这个前提不成立,我会毫不犹豫退回 Electron。工具没有优劣,只有适不适合你手上的那摊事。
给想做桌面 AI 工具的人留个清单
- 先算清楚:你的安装包要不要带模型、大资源?带,就别被「几 MB」迷了眼。
- 打包前用非最新系统的真机过一遍 UI,WebView 版本差异是隐形雷。
- 流式输出走 event 别走 invoke,交互模型要提前重构。
- 模型推理是 sidecar 自己接,Tauri 只给积木不给成品。
- 把签名公证和自动更新的成本算进排期,它们不是上线后的小事,是上线前的大头。
做桌面端这一年,我最大的收获不是学会某个框架,而是接受了一个事实:选型时文档宣传的那句口号,往往刚好是你上线后第一个要还的债。
参考:Tauri 官方文档(tauri.app,v2 分发 / 更新 / 进程通信章节)、HarnessDesk 项目实践经验。