Tauri 是什么:与 Electron 的架构对比
如果你写过后端或前端,大概听说过「桌面应用 = Electron」这个等式。Tauri 想做的事情很简单:把 Electron 里的 Chromium 换成操作系统自带的 WebView,把 Node.js 主进程换成 Rust,其余的开发体验尽量保持不变。结果就是安装包从动辄一百多 MB 缩到个位数 MB,内存占用也显著下降。本篇先把两个方案的架构摊开对比,帮你判断自己的项目适不适合上 Tauri。
一、Tauri 的核心架构
Tauri 应用由两部分组成:Rust 写的核心进程,和前端页面所在的 WebView。Rust 进程负责窗口创建、系统调用、文件操作等能力;前端仍然是你熟悉的 Vue、React 或者原生 JS。两端通过 IPC(进程间通信)连接,前端用 invoke 调用 Rust 注册的命令,Rust 也可以通过事件系统向前端推送消息。
与 Electron 最大的不同在于渲染层:Tauri 不打包浏览器。Windows 上用 WebView2(Edge 内核),macOS 上用 WKWebView(Safari 内核),Linux 上用 WebKitGTK。这意味着安装包里没有几十 MB 的 Chromium,代价是你需要处理不同平台 WebView 的兼容性差异——好在现代 WebView 都已支持 ES2020 语法,日常开发几乎无感。
二、与 Electron 的逐项对比
下面这张表把两个方案的关键维度做了对比,数字均为常见量级,具体以各自官方文档为准:
| 维度 | Electron | Tauri 2.x |
|---|---|---|
| 渲染内核 | 内置 Chromium | 系统 WebView |
| 主进程语言 | Node.js | Rust |
| 安装包体积 | 约 60 至 150 MB | 约 3 至 10 MB |
| 空载内存 | 约 150 至 300 MB | 约 50 至 120 MB |
| 进程模型 | 主进程加多渲染进程 | 单核心进程加多 WebView |
| 权限控制 | 主要靠沙箱与 CSP | Capability 权限文件 |
从量级上能直观看出差异来源:Electron 的体积和内存主要是 Chromium 本身,而 Tauri 只为 Rust 核心付出极小的代价。对工具类、效率类应用来说,这个差距直接决定用户体验。
另一个重要区别在安全模型。Electron 默认渲染进程拥有 Node 能力,需要开发者手动关闭 nodeIntegration、配置 CSP;Tauri 2 则反过来,前端默认什么都干不了,必须在 Capability 文件里显式声明允许哪些插件、哪些作用域。关于这套模型,后续「权限模型:Capability 与作用域」会详细展开,也可先看 Rust 入门建立语言基础。
三、什么时候选 Tauri
不是所有桌面应用都适合 Tauri。根据社区反馈和实际项目经验,适合与不适合的场景大致如下:
| 适合 Tauri | 需要斟酌 |
|---|---|
| 工具类、效率类应用 | 强依赖浏览器专有 API 的应用 |
| 对包体积敏感的分发场景 | 需要多渲染进程复杂架构的应用 |
| 愿意引入 Rust 处理核心逻辑 | 团队完全没有 Rust 学习预算 |
| 需要精细的权限与安全控制 | 依赖大量 Node 生态现有包 |
判断标准其实就两条:你能否接受用 Rust 写核心逻辑,以及你的前端能否在系统 WebView 里跑起来。如果两点都成立,Tauri 带来的体积、内存与安全收益是实打实的。
四、Tauri 2.x 相比 1.x 的变化
如果你看过早期教程,要注意 2.x 有几个破坏性变化。首先是权限系统重构:原来的 allowlist 被 Capability 文件取代,权限粒度更细,且支持按窗口分配。其次是插件体系官方化,文件系统、对话框、通知、Shell 等能力都拆成独立的 tauri-plugin-* crate,按需引入。最后是配置文件 schema 调整,tauri.conf.json 的结构有变化,新建项目时脚手架会生成符合 2.x schema 的模板。
五、一个最小例子的观感
在深入之前,先看一眼 Rust 端的入口长什么样,建立整体印象:
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
#[tauri::command]
fn greet(name: &str) -> String {
format!("你好,{}", name)
}
前端那边只需一行 invoke('greet', { name: '世界' }) 就能拿到返回值。整个流程的细节会在「前端调用 Rust:invoke 与命令系统」里展开,这里先体会到「Rust 注册命令、前端调用」这一基本节奏即可,API 形态以官方文档为准。
六、迁移成本的现实评估
团队从 Electron 迁移到 Tauri,真正贵的不是改框架,而是把核心逻辑从 Node 搬到 Rust。评估迁移成本时可以用下面这张表把工作分类:
| 工作类型 | 迁移难度 | 说明 |
|---|---|---|
| 纯 UI 代码 | 低 | 框架不变,基本直迁 |
| 调用 Node 生态的逻辑 | 中高 | 需找 Rust 等价 crate |
| 主进程窗口管理 | 中 | API 对照重写 |
| 原生模块与 C 扩展 | 高 | 需要 FFI 或重写 |
务实的路径是渐进式:先用 Tauri 起一个新壳,前端代码整体迁入,Rust 端只实现最必要的命令;其余逻辑先放在本地 HTTP 服务里过渡,再逐步搬进 Rust。这样每一步都有可运行的应用,而不是憋一个大迁移。对于就要上线的产品,换技术栈的收益要低于交付稳定性,这类决策建议把「量级」的体积收益与团队学习成本一起摆上桌面再定。
社区里大量 Electron 应用长期存在的内存抱怨,在 Tauri 上大多自然消失,但新问题会出现在 Rust 编译时间与依赖管理上。任何技术选型都是交换,想清楚换走的是什么、换来的是什么,比单看安装包体积更有意义。
Electron 与 Tauri 的选择最终是团队能力与产品形态的选择。如果你做的是内部工具、开源软件或者对体积敏感的消费级产品,Tauri 的收益立竿见影;如果你的应用强依赖 Node 生态或需要复杂的渲染进程架构,继续用 Electron 也完全合理,两者都是成熟方案。把本篇的架构图记住:Rust 核心、系统 WebView、IPC 通信,后续每一章都在这个骨架上添肉。
顺带说说嵌入式视角。Tauri 的 Rust 核心还可以编译到其他平台形态,官方对移动端(iOS 与 Android)也提供了支持路径,同一份核心逻辑有机会服务更多形态。这意味着投入 Tauri 学到的 Rust 能力,并不仅限于三个桌面平台。当然移动端的支持成熟度与本系列专注的桌面端不同,真要做移动端建议先做技术验证再决策。本篇作为全书起点,确立了后续所有章节的语境:体积小、能力强、Rust 核心、系统 WebView,下一章开始动手准备环境。
给还在犹豫的读者最后一个判断框架。先问三个问题:这个应用的核心能力是否多半在 Rust 生态里能找到现成实现?团队是否有半年以上的耐心积累 Rust 代码?产品对包体积与内存是否真的敏感?三个问题里两个回答是肯定的,Tauri 就是合理选择;两个否定,Electron 依然是稳妥的路径。技术选型最怕的不是选错,而是跟风,量体裁衣才是工程态度。本篇讲清了「是什么与为什么」,下一篇开始解决「怎么做」,先从环境准备入手,把开发机器武装好。
关于学习路径再多说两句。这本书的顺序就是建议的学习顺序:先认识架构与环境,再把命令与事件两套通信跑顺,接着补 Rust 语法与异步,最后研究插件权限与打包发布。每章都配了可运行的代码片段,跟着敲一遍比通读两遍更有收获。如果你已经有 Rust 基础,可以跳过语法速成那章直接进入异步与线程。无论怎么走,动手做出一个能跑的应用永远是第一步,其余的打磨都建立在这个前提之上。希望这本书能帮你把桌面应用这件事,变成一件有章可循、可以持续积累的手艺。
延伸阅读
- Rust 入门:写 Tauri 命令前必备的 Rust 语法基础
- Claude Code 指南:用 AI 辅助生成 Rust 命令与前端代码的实践
- 环境准备:Rust、Node 与系统依赖——下一篇介绍如何搭建开发环境
