Skip to main content
返回博客
博客

为什么我们选择用 Tauri 而不是 Electron 来构建 MadoHub

解释为什么我们为一个桌面开发工具选择 Tauri v2 - 性能、二进制体积,以及 Rust 在系统集成上的优势。

在开始构建 MadoHub 时,我们有一个明确需求:做一款带 Web UI 的桌面应用,既能管理 PTY session,读取文件系统,又能深入对接系统进程。真正可选的方案只有两个:Electron 和 Tauri。

我们选了 Tauri。原因如下。

二进制体积

Tauri 最常被提到的优势,是二进制体积。一个空的 Electron 应用大约 150MB,因为它会捆绑完整的 Chromium 浏览器。Tauri 应用通常从 5MB 以下起步,因为它使用系统原生 webview(macOS 上是 WebKit,Windows 上是 WebView2,Linux 上是 WebKitGTK)。

对于开发者工具来说,二进制体积比你想的更重要。开发者对自己安装什么非常挑剔。一个“效率工具”如果要下载 200MB,天然就会让人怀疑;10MB 的下载量则会传递出“轻量且专注”的信号。

但二进制体积其实不是我们做决定时最重要的因素。

Rust 后端

我们选择 Tauri 的真正原因,是 Rust 后端。

MadoHub 需要同时管理 PTY session、监控 tmux pane、解析 JSONL 文件、发起路由 API 调用,以及处理文件系统操作 - 而且这些都要并发进行。这些都是系统级操作,Rust 在这方面优势明显:

没有 GC 的内存安全:PTY 管理涉及进程生命周期、文件描述符和信号处理。在 Node.js(Electron 的后端)里,进程管理 bug 可能会泄漏文件描述符,或者留下僵尸进程。Rust 的所有权模型会在编译期捕获这类问题。

真正的并发:MadoHub 会同时监控多个终端进程,在后台线程里轮询 tmux pane,并发起路由 API 调用。Rust 的 async runtime(tokio)可以低开销地处理这些事情。Node.js 虽然能做 async I/O,但像解析大型 JSONL 文件这种 CPU 密集型工作会阻塞事件循环。

结构化错误处理:系统操作的失败方式通常很可预测 - 文件不存在、进程退出、API 超时。Rust 的 Result 类型强迫我们处理每一种失败路径。在路由代码里,这意味着“session file not found,回退到 CWD 解析”这种干净逻辑,而不是某个莫名其妙的 undefined 错误把路由管线直接打崩。

我们的 Rust 工作区

MadoHub 的后端拆成了 7 个专注的 crate:

Crate责任
madohub-ptyPTY session 管理、tmux 集成
madohub-pane用于团队监控的 tmux pane 轮询
madohub-agentAgent 路由、JSONL 解析、API 调用
madohub-gitGit 操作(status、commit、push)
madohub-team从 ~/.claude/teams/ 里检测团队
madohub-persistence将画布状态序列化到 ~/.madohub/
madohub-core共享事件发射器 trait

这种模块化结构意味着每个 crate 都可以独立测试,而且编译时间还能保持可控,因为没变的 crate 不需要重复编译。

前端故事

Tauri 的前端就是一个 webview,渲染的是标准 Web 应用。我们使用 React 19 + TypeScript + Tailwind CSS + Zustand 做状态管理 - 这套栈和你做 Web 应用时用的一样。

前后端之间通过 Tauri 的 command 系统通信 - 本质上就是带类型的 IPC。前端调用 Tauri command,Rust 后端执行,然后结果返回。对于流式数据(终端输出、路由事件),Tauri 提供了 event 系统。

还有一个常被忽视的优点:webview 使用系统原生的渲染引擎,这意味着它会继承平台的文本渲染、滚动手感和无障碍特性。MadoHub 里的文字看起来原生,是因为它 确实 是原生渲染。

我们放弃了什么

Tauri 也不是没有代价。

跨平台 webview 差异:WebKit(macOS)和 WebView2(Windows)在一些边界场景上渲染行为不同 - CSS backdrop-filter 不一样,某些滚动行为也不同,新一些的 Web API 上线时间也不一致。我们确实碰到过几次,主要是在动画和模糊效果里。

生态更小:Electron 有十多年的插件、调试工具和社区经验积累。Tauri 的生态增长很快,但还年轻。我们有些东西得从头做,而如果在 Electron 里,可能直接就是 npm 包。

Rust 学习曲线:我们的前端团队主要是 TypeScript 开发者。为后端写 Rust 需要一段上手时间。对于系统级代码来说,这个回报是值得的,但前期投入是真实存在的。

实际性能

对于 MadoHub 这种工具来说 - 你可能同时开着 5 个终端图块,每个都在流式输出 PTY,而路由系统还在监控完成状态和轮询 tmux pane - 性能不是理论问题。画布掉帧、终端渲染卡顿、路由触发延迟,都会直接影响可用性。

在我们的基准测试里,MadoHub 在 8 个活跃终端图块的情况下,大约只占 120MB 内存。一个等效的 Electron 应用,在还没打开任何终端之前,仅 Chromium 开销就会达到 300MB 以上。

正常运行时的 CPU 占用(终端活跃、路由空闲)保持在 5% 以下。活跃路由时(API 调用 + JSONL 解析 + 内容投递),它会短暂升到 15% 到 20%,然后回落到基线。

如果重做一次,还会选 Tauri 吗?

答案是毫无疑问:会。对于这类应用,Rust 后端 + Web 前端 的组合非常自然,特别适合需要深度系统集成的开发者工具。

如果是更简单的应用 - 比如除了基本文件 I/O 之外没有任何系统交互 - 选择就没那么明确了。Electron 的成熟度和生态体量,在很多场景里会是更务实的选择。

但对 MadoHub 来说,后端要管理并发 PTY session、监控系统进程、并以高吞吐解析结构化数据,Rust 不只是性能优化,它还是一种正确性保证,让我们可以更有信心地发布。