ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Tauri实战:桌面应用从224MB降到4.7MB,六大跨平台方案对比

Tauri实战:桌面应用从224MB降到4.7MB,六大跨平台方案对比 前几天一个朋友找我诉苦他们的 Electron Vue 桌面客户端安装包已经涨到 224MB 了公司内网分发还好说外网用户一看下载体积直接劝退。我说你换个思路试试前端还是那套 Vue把后端从 Node.js 换成 Rust用 Tauri 那套方案重打包一次。他半信半疑地试了结果安装包从 224MB 直接干到 4.7MB启动速度还快了一大截。这篇文章就把这次实践完整复盘一下顺带把市面上常见的 6 种跨平台桌面方案放在一起横向对比讲讲体积差距背后的原理以及 Tauri Vue 从搭建到打包的完整实操流程。适合正在做桌面客户端选型、或者被 Electron 安装包体积折磨过的团队参考。1. 六大跨平台桌面方案全景先看这张对比表桌面客户端开发这两年特别热闹光是“跨平台”这个赛道能打的方案一只手数不过来。我按技术栈和生态成熟度筛出了最常被拿出来对比的 6 种Electron、Tauri、Wails、Flutter Desktop、PySide6Qt for Python、Qt/C 原方案。它们的目标都是“一套代码多端运行”但底子完全不同出来的产物差别也大得离谱。1.1 方案阵容与选型背景先说 Electron严格来说它不是一门语言而是一个运行时把 Chromium 浏览器内核和 Node.js 打包在一起前端工程师用 HTML/CSS/JS 写界面Node.js 负责调用系统能力。这套组合在开发体验上几乎无敌生态也最成熟Slack、VS Code、Discord 都是它的代表作。代价就是安装包体积和内存占用一直被人吐槽。Tauri 是这次横评的主角它的思路是用 Rust 写后端前端照样用 Web 技术Vue、React 都行但不再内置 Chromium而是调用操作系统自带的 WebView 组件渲染界面。这个差异直接决定了两者在体积上的巨大鸿沟。Wails 和 Tauri 思路类似用 Go 写后端同样复用系统 WebView区别主要在语言生态和 Rust 与 Go 的各自优势上。Flutter Desktop 是移动端跨平台框架 Flutter 的桌面延伸用 Dart 语言和自绘 UI 引擎不走 WebView渲染性能很稳。PySide6 是 Qt 官方钦定的 Python 绑定适合 Python 技术栈的团队做工具类软件但打包体积和分发体验一直是痛点。Qt/C 则是传统原生 GUI 方案里的常青树性能天花板最高代价是开发效率相对低对前端工程师尤其不友好。1.2 核心指标对比表我根据自己的实测和使用经验把六个方案的关键指标整理成一张表方便你直观感受差距方案后端语言界面技术安装包体积量级运行时内存空应用冷启动速度生态成熟度适合场景ElectronJavaScript/Node.jsReact/Vue/任意 Web150MB - 250MB150MB - 300MB1.5s - 3s非常成熟Web 团队快速交付复杂业务TauriRustVue/React/任意 Web3MB - 15MB30MB - 80MB0.4s - 1s快速成长仍在完善追求小体积高性能Web 团队 Rust 支撑WailsGoVue/React/任意 Web8MB - 20MB30MB - 80MB0.4s - 1s社区中等Go 团队想摆脱 Electron 体积包袱Flutter DesktopDartFlutter Widget10MB - 20MB50MB - 120MB0.5s - 1s移动端沉淀后逐步成熟移动端团队统一技术栈PySide6PythonQML / Widgets100MB - 200MB80MB - 150MB1s - 2s背靠 Qt稳定但繁琐Python 生态工具类、内部系统Qt/CCQML / Widgets10MB - 50MB可裁剪50MB - 100MB0.3s - 0.8s非常成熟性能要求极高长期重投入这张表里的数字是数量级参考不同项目会因为依赖多少、是否压缩而有浮动。但一个很明显的趋势是凡是复用系统 WebView 的方案安装包体积都小一个量级凡是自带浏览器或者自带解释器的方案体积都下不来。理解了这一点后面的选型思路就很清晰了。2. 为什么 Electron 安装包直奔 224MB而 Rust Vue 能压到 4.7MB很多做前端的朋友第一次听说 Tauri 能把安装包做到几 MB第一反应是“假的吧”。其实只要搞懂 Electron 那 200 多 MB 到底装了什么再回头看 Tauri 的体积逻辑你就知道这不是魔术纯粹是架构设计上的降维打击。2.1 Electron 的体积来源每个用户都重新下载一个“Chrome Node”Electron 安装包的体积构成几乎没有秘密它内置了完整的 Chromium 渲染引擎这套东西在 Windows 上差不多要占 100MB 以上macOS 上差不多 70MB 起步再加上 Node.js 运行时几十 MB然后是你的业务代码、依赖库、图标、资源文件七七八八加起来轻松突破 200MB。我那个朋友的项目里还集成了一堆音视频处理、文件解析相关的 Node 原生模块每个都要把动态链接库塞进包里。有人可能会说那 Electron 的体积大就大一点呗反正现在固态硬盘便宜、带宽也快。问题在于这 200 多 MB 不是装一次就完了而是每个用户都要重新下载一遍。拿一个 10 万日活的应用来算每次发版至少要分发 20TB 级别的流量CDN 账单、用户下载时长、安装失败率都是实打实的成本。用户从点击下载到打开应用往往要等一两分钟心理上很容易流失。224MB 这个数字还不是最夸张的。我在一些企业内网系统里见过接近 400MB 的 Electron 安装包原因是里面塞了各种自定义字体、离线地图、大体积模型文件。Electron 的架构决定了你很难把体积控制在 100MB 以内因为你动的只是业务那几 MB而浏览器内核的底子是动不了的。2.2 Tauri 的体积逻辑不重复造浏览器直接借用系统 WebViewTauri 的聪明之处在于它把 Chromium 这个“重资产”从安装包里拿掉了。Windows 上调用系统自带的 WebView2也就是 Edge 的渲染内核macOS 上调用 WKWebViewLinux 上调用 WebKitGTK。这些组件绝大多数用户的系统里已经有了不需要你的安装包再带一份。于是 Tauri 安装包里剩下来的主要就是两样东西Rust 编译出来的原生二进制程序以及前端构建后的静态资源。Rust 的二进制在采用体积优化编译后可以做到很小一个完整的桌面应用主程序压缩前可能就 5MB 上下压缩后更小。而 Vue 这类前端框架构建出来的产物对于一个中等复杂的界面来说通常也就几百 KB 到 1MB 左右。你可能要问那 4.7MB 是怎么来的以我朋友那个项目为例前端资源大概 500KBRust 二进制压缩后在 3MB 左右再加上安装脚本、基础配置、图标最后拿 NSIS 或者 AppImage 打完包就是 4.7MB。如果继续做极端优化关掉默认没用的功能模块、用 UPX 这类工具再压一层甚至能逼近 3MB。但我的建议是不要为了数字好看而牺牲稳定性和兼容性4.7MB 已经是一个很健康的水平了。2.3 比体积更重要的两个数字内存占用和启动速度体积大只是第一层痛点真正让 Electron 被诟病的还有内存和启动速度。因为 Electron 本质上是一个跑在你自己设备上的完整浏览器它要加载渲染进程、GPU 进程、网络进程等一系列子进程一个空窗口吃 150MB 内存是家常便饭。Tauri 复用系统 WebView 之后省掉了整套进程架构只保留渲染界面所需的最小 WebView 实例和 Rust 后端。我实测下来同样一个 Vue 页面Electron 空应用内存占用在 180MB 左右Tauri 只有 50MB 上下。如果你做的是常驻后台的桌面工具几十台电脑合在一起内存节省非常可观。启动速度上差距也很明显。Electron 冷启动要拉起 Chromium 那一堆初始化流程再加上解析 Node 模块1.5 秒起跳是常态。Tauri 只需要启动 Rust 进程并调用系统 WebView冷启动基本在 500 毫秒以内用户点击图标的感知是完全不同的。用一个不恰当但很生动的类比Electron 是开一辆大房车出门什么都有但启动、耗油都是开销Tauri 是开一辆小车路上用已有的服务区轻装快跑。3. 实操Tauri Vue 从零搭建到打包出 4.7MB 安装包理论说得再多不如动手跑一遍。这一节我把 Tauri Vue 从环境准备到最终打包的完整流程写出来包含我踩过的坑和常用的瘦身参数。这套流程在 Windows、macOS、Linux 上大差不差我以 Windows 环境为主需要跨平台的差异我会单独标出来。3.1 环境准备Rust、Node、平台依赖一个都不能少第一步是装 Rust。官方推荐用 rustup 工具链安装在终端执行 rustup-init.exe一路默认就行。装完以后确认一下 cargo 和 rustc 都在 PATH 里cargo --version rustc --versionRust 工具链本身就比较大如果网络条件一般可能会比较慢耐心等待即可。装完 Rust 之后就是 Node.js建议直接装最新 LTS 版本我这边用的是 18 以上的版本配合 pnpm 或者 npm 都行。Vue 项目本身需要 Node 环境来跑 Vite 开发服务器和打包前端资源。然后处理平台相关的依赖。Windows 上需要确保系统有 WebView2 运行时Win10 1803 以上基本都自带还需要安装 Microsoft C Build Tools因为 Rust 的某些原生依赖需要 MSVC 编译。macOS 上只需安装 Xcode Command Line Tools。Linux 上最麻烦需要安装 WebKitGTK 等一堆开发库Ubuntu 系的命令大概是sudo apt update sudo apt install libwebkit2gtk-4.0-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev这里特别提醒一下很多人在 Linux 上打包失败就是提前没装全这些依赖。别等到编译到一半报找不到 webkit2gtk 再回来补那会非常痛苦。3.2 用官方脚手架创建项目并跑通开发模式环境准备好之后用官方脚手架初始化项目。输入下面命令按提示选择 Vue TypeScript 模板npm create tauri-applatest cd 你的项目名 npm install npm run tauri dev命令跑完之后你会看到一个 Tauri 窗口弹出里面渲染的是 Vue 页面。这个窗口由系统 WebView 渲染而不是一个完整的浏览器窗口这也是它轻量的根本原因。项目结构上根目录的 src 文件夹是前端 Vue 代码src-tauri 文件夹是 Rust 后端代码核心配置在 src-tauri/tauri.conf.json 里。开发状态下Tauri 会启动 Vite 开发服务器然后用 WebView 加载 http://localhost:5173 这个地址而生产打包时它会自动把 dist 目录下的前端资源内嵌进二进制不依赖外网服务器。对于 Vue 工程师来说前端部分和以前写 Web 应用没有任何区别唯一的注意点是 Vue Router 不要用 history 模式。这里再啰嗦一句如果你的项目用了 createWebHistoryTauri 里刷新页面很容易白屏因为生产环境下没有传统服务器去做 URL fallback。最简单粗暴的解决办法是用 createWebHashHistory后面第 5 节我再细讲。3.3 打包配置Cargo 瘦身参数与 Tauri 打包目标开发跑通之后就可以开始准备打包了。首先打开 src-tauri/Cargo.toml在文件末尾追加一个 release profile这对最终安装包体积影响极大[profile.release] codegen-units 1 lto true opt-level s panic abort strip true这几个参数各有用处lto true 开启链接时优化让编译器在链接阶段做跨模块优化能有效减小二进制体积codegen-units 1 限制并行代码生成单元虽然会让编译慢一点但配合 LTO 体积优化更彻底opt-level s 让编译器以“优化体积”为目标生成代码而不是默认的速度优先panic abort 去掉 Rust 的堆栈展开信息strip true 直接剥离符号表对减小体积帮助极大。接着看 src-tauri/tauri.conf.json这块决定你要产出什么格式的安装包。Windows 上一般用 nsisLinux 上常用 deb 或者 AppImagemacOS 用 dmg。我的习惯是bundle: { active: true, targets: [nsis], icon: [icons/icon.ico] }如果你在 Linux 上打 deb 包可能会遇到 fpm 相关的报错这个我在第 5 节单独讲。打包前先用 cargo check 和前端 build 确认没报错再执行npm run tauri build第一次编译会特别慢因为要把几百个 Rust crate 全部拉取并编译一遍卡个几分钟甚至十几分钟都很正常。编译完成后在 src-tauri/target/release/bundle/ 目录下就能看到安装包文件。我朋友的项目在这个状态下还没做体积优化只启用了默认配置打包出来大概 8MB 多做完瘦身之后才压到 4.7MB。3.4 前端资源与二进制体积的平衡很多人以为 Tauri 体积小前端构建产物肯定也做了极端压缩。这里我给一个中肯的建议前端部分不要刻意追求极致压缩保证合理的构建优化就够了。Vite 默认就是用 Rollup 做生产构建已经会压缩混淆 JS 和 CSS对于 Vue 项目来说产物通常在几百 KB 到一两 MB 之间。前端资源会被 Tauri 以某种形式嵌入到最终二进制里所以前端体积越大安装包也越大。实际操作中我会定期检查 src-tauri/target 目录下生成的 exe 或二进制文件大小再对比 dist 目录的前端产物大小。如果发现二进制文件暴涨优先检查是不是在 main.rs 里引入了太大的依赖或者是图标资源没有压缩。Tauri 本身的默认功能模块很多如果你不需要某些插件比如自动更新、隧道穿透等在 Cargo.toml 里去掉对应 feature也能省下一些体积。但注意不要一上来就全套裁减等打包流程稳定之后再逐步做减法。4. 其他五种方案的打包实战与体积实录横评的意义在于对照。光看 Tauri 一家好不够我把其他几种方案各自的打包体感和体积都拉出来遛一遛这样你在选型的时候才有完整的坐标系。4.1 Electron 的 224MB 怎么来的能瘦到多少Electron 项目用 electron-builder 打包是主流方案。一个 Vue Electron 项目打包产物里至少有electron.exe 和配套的 dll120MB 上下app.asar若干 MB 到几十 MB取决于业务和依赖各种语言包和资源文件。即便你用 asar 压缩把项目源码和 node_modules 塞进一个包体量仍然非常大因为大头的 chrome_100_percent.pak、icudtl.dat 这些资源是省不掉的。我试过给 Electron 做瘦身发现能动的只有业务代码和依赖核心运行时根本动不了。一个空 Electron 应用打包出来最少也要 60MB 左右稍微加几个依赖就上 150MB。反过来想224MB 其实不是某个人的打包姿势有问题而是这套架构的基线太高。如果你想在 Electron 体系里把安装包压到 100MB 以下唯一现实的路线是引入按需下载 CDN 资源的机制但那是把产品架构搞复杂跟桌面端“一键安装离线可用”的初衷冲突了。4.2 WailsGo Vue轻量方案的第二梯队Wails 和 Tauri 思路几乎一致也是复用系统 WebView区别在后端用 Go。我尝试过一个 Wails Vue 的简单项目打包出来 9MB 左右比 Electron 强太多在开发体验上Go 的编译速度和简单语法对后端工程师非常友好。Wails 的初始化命令也简单wails init -n myproject -t vue wails build体积方面Wails 比 Tauri 大一些主要因为 Go 的运行时包含 GC 和调度器静态链接的二进制体积天然比 Rust 大。但如果你团队的主力语言是 Go这个差距完全可以通过开发效率弥补。它和 Tauri 的最大区别不在性能而在 Rust 和 Go 之间的选择Rust 更节省资源但也更考验工程师Go 上手快、坑相对少。4.3 Flutter Desktop 与 PySide6 的真实体感Flutter Desktop 这两年势头很猛用 Dart 编写UI 是自绘引擎渲染不依赖系统 WebView所以渲染一致性非常强。打包一个简单的桌面应用体积大概 10-20MB内存占用比 Tauri 高一些但比 Electron 好很多。如果你们团队本来就是 Flutter 移动端出身顺手做桌面是首选。PySide6 则是另一条路线。Python 开发工具类应用确实快Qt 的控件系统也成熟但打包是绕不过去的痛点Python 解释器、PySide6 的 Qt 绑定库、各种依赖全部要打包进去安装包很容易超过 150MB。更难受的是Qt 的库文件非常多即便你用 PyInstaller 打包最后得到一堆散文件分发体验远不如单文件安装包。我自己的结论是PySide6 适合做内部工具或脚本型桌面应用真要对外发布给海量用户体积这道坎很难迈过去。4.4 Qt/C 和 Rust 原生 UI 方案的体积下限如果你追求极致体积Qt/C 是一条路。Qt 支持静态编译把用到的库全部揉进一个可执行文件一个简单的界面程序几 MB 就能搞定。但 Qt 静态编译存在许可和工程复杂度问题而且整个编译配置非常折腾小团队未必承受得起。Rust 生态里也有 egui 这类纯原生 UI 框架二进制体积可以做到 1MB 以内但 UI 的表达能力比 Web 技术栈弱不少适合做调试面板、监控工具这类偏工具型的界面而不是业务复杂的客户端。5. 常见问题与排查技巧Linux 打包、路由适配、编译踩坑任何工具链都有一堆“文档里没写明白”的坑Tauri 也不例外。我把自己实际遇到过的、以及身边同事反馈频率最高的问题整理成一份速查省得你重复踩雷。5.1 Linux 打包时 fpm 报错怎么办标题里那个朋友的项目在 Linux 上打包 deb 时就遇到过 fpm 报错。fpm 是 Ruby 写的打包工具Tauri 在生成 deb/rpm 包时会调用它。常见的报错原因包括系统 Ruby 版本太老、fpm 依赖的 gem 没装全、没有写权限等。我的建议是能不用 fpm 就不要手动缠斗。Tauri 在 Linux 下优先打 AppImageAppImage 的好处是不依赖系统库分发也简单。如果你的目标发行版是 Ubuntu/Debian 系打 deb 包之前确保系统里有 ruby-dev 和 fpm或者直接把打包放到 CI 的 Docker 容器里跑。Tauri 官方提供了 tauri-action 的 GitHub Action里面有预配置的 Linux 打包环境能省掉一堆本地环境问题。5.2 Vue 路由在 Tauri 里刷新白屏的坑这个问题几乎每个用 Vue Router 的 Tauri 项目都会遇到。开发环境没问题但打包后一刷新页面就白屏。原因是生产环境下 Tauri 用的是自定义协议加载前端资源根本没有服务端来处理 URL 路径。解决办法很简单用 hash 模式而不是 history 模式import { createRouter, createWebHashHistory } from vue-router const router createRouter({ history: createWebHashHistory(), routes })如果你硬要用 history 模式就得在 Rust 侧写自定义协议处理 fallback复杂度和收益不成正比。反正桌面端应用不依赖 URL 的语义化hash 模式是最稳的选择。5.3 Windows 打包的图标、签名和路径问题Windows 打包踩坑最多的三个点图标、签名、路径。Tauri 对图标格式有硬性要求Windows 必须提供 .icomacOS 必须提供 .icnsLinux 提供多个尺寸的 .png。官方推荐用npm run tauri icon命令从一张 1024x1024 的 PNG 自动生成全套图标千万不要自己拿 jpg 改后缀名糊弄。另外项目路径里不要有中文NSIS 脚本对非 ASCII 路径支持不好这个坑我踩过一次后来养成了所有项目一律英文路径的习惯。代码签名这块如果你要公开发布Windows SmartScreen 会拦截没有签名的安装包Tauri 官方文档有签名配置说明建议在 CI 里集成不要拖到发布前才处理。5.4 Rust 首次编译慢、学习门槛高怎么办很多前端项目组对 Tauri 望而生畏主要怕 Rust。先说编译慢的问题首次编译要拉取并编译所有依赖慢是正常的但后续增量编译会快很多。建议在用户的设置里给 cargo 配置镜像加速依赖下载另外官方脚手架生成的项目默认就配了缓存机制没必要提前优化。Rust 语言本身确实比 JavaScript 硬核但 Tauri 日常开发里你用到的 Rust 只是冰山一角无非是创建窗口、注册命令、读写文件再加上几个结构体和错误处理。我建议前端工程师从这本书入手看到 async、future、生命周期这些概念时不用恋战先用起来等真的碰到性能瓶颈再回来深入研究。Rust 安全性的心智负担在高并发系统里才是主角在 Tauri 这种场景里你完全可以把后端写得像简单脚本一样直白。6. 选型建议什么时候选 Electron什么时候选 Tauri写了这么多对比最后还是得落到真实决策上。选型没有绝对正确只有适合不适合。如果你的团队是纯前端出身业务又特别复杂比如要做在线文档、IDE、复杂富文本编辑器这类系统还要大量使用 Node.js 生态里的原生模块那 Electron 仍然是最稳的选择。VS Code 就是典型例子它靠 Electron 做到了一版代码全平台跑积累的周边生态无可替代。这个赛道里体积和内存不是核心矛盾迭代速度和稳定性才是。但如果你做的是面向消费者的工具类软件比如视频播放器、桌面笔记、聊天工具、文件管理工具用户对安装包体积和启动速度特别敏感前端又有 Vue/React 技术沉淀那 Tauri 是一个非常值得押注的方向。它保留了 Web 技术栈的开发效率同时把体积和内存两条指标拉回原生水准。前提是团队里有一两个人能扛住 Rust 后端或者愿意花两周左右时间补 Rust 基础。至于中间情况Go 团队选 Wails移动端团队选 Flutter DesktopPython 团队做内部工具选 PySide6性能极致要求且有长期投入能力的选 Qt/C。这些选择都不丢人关键是搞清楚自己的约束条件时间、人员技术栈、目标用户网络环境、发布渠道平台列出来以后一对照答案基本就出来了。我个人的体会是Tauri 不是银弹它的坑并不比 Electron 少尤其是 Linux 打包和系统 WebView 兼容性上有时候你会怀念 Electron 的“一套 Chromium 走天下”。但当你把安装包从 224MB 压到 4.7MB亲眼看到用户下载耗时从几分钟变成几秒钟就会觉得这些折腾都值了。最后再分享一个小技巧不管最后选哪个方案都别只看官方文档把目标平台的用户环境摸清楚——系统版本分布、网络带宽、是否常驻内存这些才是决定桌面端体验的真正变量。
返回列表