尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Electron到Tauri迁移实战:应用体积从224MB降至4.7MB

Electron到Tauri迁移实战:应用体积从224MB降至4.7MB 说实话我第一次看到“224MB 变 4.7MB”这个数字时第一反应是这也太夸张了。但当我真的把一个还在用 Electron 写的内部工具项目用 Rust Vue 的方式重新做了一遍桌面壳之后才发现这数字不但不夸张甚至还有继续压缩的空间。这个标题背后其实是近几年跨平台桌面方案的一个明显拐点大家不再默认 Electron 是唯一答案而是开始关心安装包体积、内存占用、启动速度这些平时不太敢碰的“Electron 老毛病”。这篇文章我不会只吹 Tauri而是把市面上真正能打的 6 种跨平台桌面方案放一起横评重点拆解我从 Electron 迁移到 Tauri Vue 的完整过程、体积是怎么从 224MB 降到 4.7MB 的以及在这个过程中踩过的坑。适合谁看如果你正在做桌面应用选型、被 Electron 的体积和内存折磨过、或者想用 Rust 给前端项目补一个高性能壳这篇文章基本就是为你准备的。1. 六种跨平台桌面方案的大盘点和选型逻辑1.1 先捋清楚“跨平台桌面方案”到底是在解决什么问题跨平台桌面方案要解决的核心问题是你写一套业务代码能不能同时在 Windows、macOS、Linux 上跑起来而不用为每个系统单独维护一套原生界面和交互逻辑。听起来很简单但实际选型时的博弈点非常多包体积、内存、启动速度、开发效率、生态成熟度、团队技术栈、还有 Web 前端资产的复用程度。市面上比较有代表性的方案我按下层技术分了几类基于浏览器内核的Electron、Tauri、基于自绘引擎的Flutter、基于原生控件的Qt、PySide6、以及一些剑走偏锋的轻量方案Wails、Neutralino.js。每一类背后都对应着一套完全不同的权衡逻辑没有绝对的好与坏只看你更在意什么。1.2 六种方案全景对比从技术栈到包体积我用自己的一个实际项目来做基准测试这个项目是一个带后台图表、音视频播放、文件导入导出功能的中型业务工具。为了方便对比每个方案都只打包同一个简化后的应用外壳不包含太多业务代码和第三方动态库。先说结论再放数据。方案底层技术安装包体积精简版内存占用空载开发语言前端复用能力ElectronChromium Node.js约 190~224MB180~300MBJavaScript/TypeScript极高Web 全家桶直接跑Tauri系统 WebView Rust 后端约 4.7~8MB60~100MBRust 任意前端高Web 资源按需缩小Flutter Desktop自绘引擎 Skia/Impeller约 18~35MB120~200MBDart较低UI 层不能直接复用Qt原生控件QWidget/QML约 15~50MB50~120MBC/Python 绑定中可用 QML 但生态不同PySide6 / TkinterCPython Qt/Tk 绑定约 80~150MB80~200MBPython低需额外包装 WebViewWails系统 WebView Go 后端约 6~12MB60~110MBGo 任意前端高类似 Tauri 的模型这里有个容易混淆的点Flutter 的包体积虽然看起来小但它需要内置自己的渲染引擎运行时内存并不比 Electron 省太多。Qt 和 PySide6 的优势是原生控件和底层操作能力强但如果你要做复杂的数据可视化界面开发效率往往不如 Web 技术栈高。Wails 的定位和 Tauri 非常像只是后端语言换成了 Go生态没有 Rust 那么“硬核”但上手门槛低很多。1.3 到底怎么选不同团队、不同场景的最优解选型这件事没有银弹但有一个很实用的判断路径。如果团队里都是前端工程师没有任何后端或系统编程经验而且产品需要快速迭代、大量复用现有 Web 组件Electron 依然是最稳妥的选择。它的开发体验和对 Chromium 的掌控力是其他方案目前还比不了的。Electron 的安装包大、内存高这些问题可以用压缩安装包、延迟加载、内存优化等手段缓解但做不到根除。如果团队有后端工程师愿意碰 Rust 或 Go而且你对安装包体积、内存占用、系统资源调用有硬性要求Tauri 和 Wails 是当前最值得押注的方向。Tauri 适合那种“前端已经写好了只想换个更轻的壳”的场景Wails 适合对 Rust 有顾虑、想用 Go 快速实现的团队。如果产品形态是需要大量自定义绘制、复杂交互动画、或者要跑在低配机器上Flutter Desktop 的自绘引擎会是一个有意思的选择但它的桌面端生态目前还没有完全成熟。如果项目本身已经有 C/Python 技术栈Qt 或 PySide6 是更稳妥的原生方案但这属于另一个赛道了和 Web 技术栈的直接竞争关系不大。2. 为什么我把目光投向了 Rust Tauri而不是继续用 Electron2.1 Tauri 的核心原理系统 WebView Rust 后端Tauri 的设计思路和 Electron 有一个根本性的不同Electron 把整个 Chromium 浏览器内核打包进你的应用不管你机器上装没装浏览器它都自带的Tauri 则反过来它直接调用操作系统自带的 WebView 组件来渲染前端界面——Windows 上是 WebView2本质是 Chromium 内核但由系统管理macOS 上是 WKWebViewLinux 上是 WebKitGTK。这样的好处是应用安装包里不再需要塞一个几十 MB 到一百多 MB 的浏览器内核包体积自然就下来了。同时Tauri 的后端不是 Node.js而是 Rust由 Rust 进程提供系统能力、文件操作、子进程管理、以及和 WebView 之间的通信桥。前端通过 JavaScript API 调用 Rust 命令Rust 也可以主动向前端发送事件这个通信模型在架构上比 Electron 的 Node.js 后端要轻得多。有人可能会问那 Rust 后端 WebView 渲染是不是性能就比 Electron 好其实不能一概而论。渲染层用的是系统 WebViewJavaScript 执行效率反而比 Electron 自带的 Chromium 略低因为系统 WebView 的版本和配置你控制不了。但关键区别在于你的业务逻辑如果主要是调用系统 API、读写文件、跑耗 CPU 的计算任务用 Rust 实现会比 Node.js 快不少而且内存占用小很多。如果你的业务逻辑绝大部分都是 Web 界面里的 DOM 操作和请求那两者差异不大真正拉开差距的是运行时开销。2.2 224MB 到 4.7MB体积是怎么被切掉的先算一笔账。Electron 打包进去的东西大致包含三个部分Chromium 内核、Node.js 运行时、你自己的业务代码和依赖。其中 Chromium 和 Node.js 占大头打底就是 150MB 以上你的 node_modules 里只要多几个重量级依赖轻松冲到 200MB 以上。Tauri 的打包结构完全不一样前端资源会被构建成静态文件压缩后一般只有几百 KB 到几 MBRust 后端编译产物是原生二进制本身很小再加上系统 WebView 由操作系统提供不占应用包体积。所以我那个项目最后打包出来 4.7MB基本就是前端静态资源 Rust 二进制 少量资源文件的重量。需要注意这里有个前提目标机器上得有系统 WebView。Windows 10/11 基本都预装了 WebView2Windows 7 这种老系统就需要额外判断和引导安装。macOS 自带的 WKWebView 是集成在系统里的问题不大。Linux 则依赖 WebKitGTK很多精简发行版不一定预装打包时需要依赖处理。这些我们在后面的实操部分再细说。2.3 前端为什么选了 Vue而不是 React 或 Svelte标题里写了 Rust Vue可能有人会觉得这只是个人偏好。其实不是选择 Vue 在 Tauri 场景下有很实际的理由。首先是体积。Vue 3 的运行时加编译器本身非常小gzip 后只有 30KB 左右比 React 全家桶小得多。Tauri 前端的核心目标就是“把静态资源压到最小”Vue 天然契合。其次是心智模型。Vue 的模板语法、响应式系统、组件划分逻辑和桌面端常见的表单、配置面板、状态管理场景很搭再加上 Vue DevTools 的远程调试能力在 WebView 里也能用开发体验不比在浏览器里差。第三是生态。Electron 时代很多现成的 Vue 组件库比如 Element Plus、Naive UI都可以无缝迁移到 Tauri 的 WebView 里因为它们本质上是纯 Web 技术不依赖 Node.js API。如果换成 React组件库的体量通常会更大对端侧包体积不友好。当然如果你团队更熟悉 React 或者 SvelteTauri 同样支持。Vue 只是我在这个项目里的选择不是唯一答案。但如果你是一个从零开始的新项目我建议认真考虑一下 Vue Tauri 的组合至少在体积和开发效率这两个维度上它接近最优解。3. 迁移实录把 Electron 项目搬到 Tauri Vue 的完整步骤3.1 环境准备Rust 安装和系统依赖Tauri 开发环境的核心有三块Rust 工具链、Node.js前端构建用、以及系统的 WebView 依赖。Rust 我用的官方 rustup 安装Windows 下还需要一个 MSVC 链接器装了 Visual Studio Build Tools 就有。macOS 上需要 Xcode Command Line Tools。Linux 下需要装 WebKitGTK、libappindicator 等一堆依赖每个发行版包名不太一样官方文档写得很清楚照着执行就行。这里有个最容易被忽略的点Rust 安装完成后一定要确认cargo和rustc在 PATH 里并且版本不是太老。Tauri 对 Rust 版本有最低要求一般建议用最新的 stable 版本。我自己踩过坑因为 rustc 版本太老编译 Tauri 时乱七八糟的报错一堆后来把所有组件升级了一遍才正常。3.2 初始化一个 Tauri Vue 项目Tauri 官方提供了一键创建项目的脚手架用npm create tauri-app就能生成。生成时可以选择前端框架demo 里就有 Vue 选项非常省事。# 创建项目交互式选择 npm create tauri-applatest # 进入目录并安装依赖 cd my-tauri-app npm install npm run tauri dev初次运行tauri dev时会编译整个 Rust 项目耗时可能比较久因为第一次要把 Tauri 的依赖全部拉下来并本地编译。这个过程对网速和磁盘 IO 都有要求建议挂代理。第一次编译成功后后续的增量编译会快很多但也要几十秒到几分钟不等。如果你是从已有 Vue 项目迁移过来其实不需要重新创建项目。最简单的方式是在一个 Vue 项目里手动加上src-tauri目录然后在package.json里加 Tauri 相关依赖和脚本即可。这样前端工程结构基本不变改动最小。3.3 核心配置tauri.conf.json 里必须改的几个字段Tauri 的配置文件是src-tauri/tauri.conf.json。有几个字段如果不改打包出来的应用会出各种问题。第一个是identifier这个字段相当于应用的唯一 IDWindows 上会被注册为应用标识建议用反向域名格式比如com.example.myapp。如果直接用默认值后面做 Windows 安装包时可能会遇到签名或卸载问题。第二个是build节点下的beforeDevCommand和beforeBuildCommand。这两个命令会在开发模式和生产构建前自动执行一般配置成前端框架的启动和构建命令。比如用 Vite 的话{ build: { beforeDevCommand: npm run dev, beforeBuildCommand: npm run build, devPath: http://localhost:5173, distDir: ../dist } }第三个是bundle节点下的targets这里决定最终生成什么格式的安装包。Windows 下可以选msi和nsisNSIS 生成的 exe 安装包体积更小、自定义选项更多Linux 下选deb、appimage或rpmmacOS 下选dmg或app。我项目里 Windows 用的 NSISLinux 用的 deb AppImage实测下来 NSIS 的安装流程对普通用户更友好。第四个是app.windows配置这里控制主窗口的标题、宽高、是否可缩放、是否透明等。如果是迁移 Electron 项目记得把原来BrowserWindow里的配置项对应翻译过来。3.4 把 Electron 的 preload / IPC 换成 Tauri 的命令调用Electron 里前后端通信通常靠ipcMain.handle配合contextBridge暴露 API。在 Tauri 里这个机制换成了 Rust 命令 JavaScript invoke。举个例子Electron 里你可能是这样定义读取文件接口的// Electron preload const { contextBridge, ipcRenderer } require(electron) contextBridge.exposeInMainWorld(desktop, { readFile: (path) ipcRenderer.invoke(read-file, path) })Tauri 里对应的 Rust 端需要在src-tauri/src/lib.rs或拆分的模块里写一个命令函数用#[tauri::command]标记use std::fs; #[tauri::command] fn read_file(path: String) - ResultString, String { fs::read_to_string(path).map_err(|e| e.to_string()) }然后在run方法里注册这个命令fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![read_file]) .run(tauri::generate_context!()) .expect(error while running tauri application); }前端调用就变成import { invoke } from tauri-apps/api/core const content await invoke(read_file, { path: C:/test.txt })需要注意Tauri 的命令参数默认是驼峰命名但 Rust 函数参数偏好蛇形命名。前端传参时Tauri 会自动把camelCase转成snake_case所以你在 invoke 里写{ path: xxx }对应 Rust 里path: String不会有问题但如果是多单词参数比如{ fileName: xxx }Rust 里要写成file_name: String这个细节很容易被忽略不改会报参数找不到的错误。3.5 用 Tauri 的 API 代替 Node.js 能力Electron 里很多常用的 Node.js 能力在 Tauri 里都有对应实现。用官方的tauri-apps/plugin-fs可以做文件读写用tauri-apps/plugin-dialog可以做文件选择对话框用tauri-apps/plugin-shell可以调用外部程序。这些插件的接口设计比直接操作 Rust IO 更接近前端习惯迁移成本很低。比如打开系统文件选择框import { open } from tauri-apps/plugin-dialog const selected await open({ multiple: false, directory: false })如果你原来的 Electron 代码里有大量 Node.js 核心模块的调用迁移时可别想着“逐个替换”最合理的做法是先把功能按边界切分涉及系统能力的部分全部走 Tauri 插件或自定义 Rust command纯业务逻辑的部分保留原样。千万别尝试在 Tauri 里装 Node.js 兼容层那样又绕回去了。3.6 打包发布从 NSIS 到 AppImage 的完整流程打包这一步是很多人最容易翻车的地方。先说 Windows。npm run tauri build会先执行前端 build然后自动编译 Rust 后端最后调用tauri-bundler生成安装包。如果你配置了 NSIS 和 MSI 两个 target生成时会有两个安装包NSIS 的 exe 一般比 MSI 小一些。我第一次打包时忘了安装 NSIS 所需的额外依赖导致打包失败其实只要确认系统装了 Visual Studio C 工具链就行。再说 Linux。deb和AppImage的区别是deb 要装系统依赖AppImage 是免安装的绿色版。AppImage 非常适合分发给用户但打包配置稍微复杂点而且体积会比 deb 大一些。Tauri 在 Linux 下的构建机如果不带webkit2gtk-4.1-dev这些包会在编译阶段直接报错排查起来很头疼。建议打包前先看一遍系统包名对照表每个发行版的包名都不一样。macOS 打包相对最简单执行npm run tauri build后只要没有打开“App Sandbox”相关限制就能生成 dmg。但要注意在没有安装 Xcode 完整环境的机器上代码签名可能会失败没有证书的话可以在打包配置里临时关掉签名。打包完成后我专门看过一次输出目录Windows NSIS 安装包 3.2MBLinux AppImage 5.1MBmacOS dmg 4.8MB。这和之前的 224MB 差距已经不是一个级别了。需要说明的是这个体积是精简版业务工具的基准如果你的应用有很多大静态资源比如内置视频、离线地图、大量图片体积肯定会上涨但大头不再是 Chromium 内核那 100 多 MB而是你自己塞进去的东西。3.7 桌面端播放 m3u8 视频的血泪坑WebView 的 UA 问题这个坑太典型了必须单独拿出来说。我的项目里需要播放局域网里的 m3u8 直播流前端用的hls.js。在 Electron 里没有任何问题但迁移到 Tauri 之后经常在vue页面里初始化播放器时控制台报出NetworkError甚至直接 403。排查到最后发现是 WebView2 的 User-Agent 里带了一串类似Edg/和WebView2的标识服务端做了 UA 白名单校验把这串标识识别成了未知或不受信任的浏览器。Electron 里 Chromium 的 UA 看起来更像普通 Chrome所以没触发这个校验。解决办法有两类。第一类是改前端请求 UA在初始化和每次请求 m3u8 分片时手动把X-Requested-With和User-Agent覆盖成一个常规浏览器的 UA。第二类是直接改 WebView 的 UA在 Tauri 的 window 配置里加userAgent字段或者用 Rust API 在运行时动态设置。我最后选了后者因为 WebView 的 UA 统一了前端就不用在每个请求里额外处理。如果你也遇到类似的流媒体播放、设备访问摄像头、麦克风、跨域 Cookie 问题优先怀疑对象就是 WebView2 的默认行为而不是业务代码。这也是 Tauri 和 Electron 一个显著的区别系统 WebView 的行为表现可能随系统版本变化这些问题在开发机上不一定会复现。4. 六种方案实测体积、内存、启动速度到底差多少4.1 我的测试方法同一套业务基准不同壳子为了避免空口对比我拿一个实际的中型业务应用做了统一测试。功能包含登录页、详情列表页、一个基于 ECharts 的图表页、一个简单的文件导入导出功能前端代码共用同一份 Vue 构建产物除了不同壳的语言桥接部分。然后分别用 Electron、Tauri、Wails、Flutter、PySide6、Qt 搭了同样的壳打包时尽量使用默认配置不做额外极限优化。测试机器是一台 Windows 11 的 i5 笔记本16GB 内存SSD。内存占用通过任务管理器和脚本轮流记录 5 次取中位数启动时间从点击启动到首屏渲染完成。4.2 横向对比数据安装包、空载内存、启动速度方案安装包体积空载内存启动到首屏时间Electron224MB约 220MB1.8sTauri (Rust Vue)4.7MB约 90MB0.9sWails (Go Vue)6.1MB约 95MB1.1sFlutter Desktop24MB约 150MB1.4sPySide696MB约 140MB1.6sQt (C)22MB约 70MB0.6s这里的数据最有说服力的其实不是安装包体积而是内存。Electron 空载就要 220MB这还只是极简窗口。真实业务场景里一旦渲染进程里跑了多个页面、devtools、GPU 进程轻松到 500MB 以上。Tauri 和 Wails 因为复用系统 WebView内存占用集中在浏览器渲染进程里一般不会超过 150MB后台任务多的场景优势更明显。启动速度上Tauri 和 Wails 优势很大主要原因是少加载了一个完整浏览器内核只初始化系统 WebView。不过启动时间和具体功能有关如果应用启动时要加载大量 JS 包差异会缩小。必须补充一句这个测试是“同等功能、默认配置”下的结果不代表所有应用都会这样。凤毛麟角的 Electron 应用经过极限优化比如用 ASAR 压缩、手动删掉 Chromium 里的无用组件、用延迟加载内存也能压到 150MB 以下但付出的工程代价非常大而且 SDK 升级后可能又回去了。4.3 这些数据背后的原理浏览器内核 vs 系统 WebViewElectron 之所以内存居高不下是因为它启动了两个甚至多套 Chromium 进程主进程、渲染进程、GPU 进程、网络服务进程每个进程都在独立跑 V8 引擎共享内存做得再好也比单个浏览器进程开销大得多。而且 Electron 打包的 Chromium 版本一般是固定的系统里已经装了新版 Chrome它也完全不会用白白占空间。Tauri 和 Wails 的方案是“借力打力”界面渲染完全交给系统 WebView后端逻辑交给 Rust/Go 原生进程。系统 WebView 本身是操作系统的一部分不会额外增加应用安装包体积Rust/Go 进程没有 V8 引擎内存占用更可控。代价是你在 WebView 里拿不到 Node.js 的所有能力文件系统和网络请求的权限模型和安全边界都要重新设计。Flutter Desktop 的自绘引擎则是走了另一条路不依赖系统 WebView也不依赖浏览器内核而是自己画 UI。渲染效率和一致性更强但它需要把完整引擎塞进安装包所以体积比 Tauri 大内存比 Qt 高。它适合不希望被浏览器限制住的应用形态但目前桌面端插件生态还在早期。4.4 什么时候你不该抛弃 Electron虽然 Tauri 看起来很诱人但有几种情况我建议你继续留在 Electron别盲目迁移。第一你的项目深度依赖 Node.js 生态比如用了 Electron 的桌面自动更新、崩溃监控、托盘通知、系统消息推送等一堆底层模块。Tauri 虽然也有更新和托盘插件但成熟度和文档丰富程度还差一截。这类项目迁移的成本会非常高收益不一定划算。第二你的团队全是前端工程师没人愿意碰 Rust。Tauri 的 Rust 门槛是真实存在的就算你只写前端不碰 Rust遇到需要自定义系统能力时还是得有人来写。如果团队没有这个能力硬上 Tauri 会拖慢进度。第三你的应用需要深度的 Chromium 定制能力比如自定义协议拦截、修改浏览器指纹、控制渲染进程调度等。这些在 Electron 里有完整的 API但在系统 WebView 里基本是黑盒。一旦你依赖了这些能力迁移成本就变得很高。5. 常见坑和排查实录迁移 Tauri 路上容易翻车的 5 个场景5.1 Windows 老系统没有 WebView2 运行时怎么办这个坑在开发机上看不出来因为开发机基本都装了 WebView2。但如果你要发布给 Windows 10 早期版本或 Windows 7 用户系统里可能没有 WebView2 运行时。Tauri 官方推荐的做法是在打包时带上 WebView2 安装引导或者下载离线安装包一并分发。在tauri.conf.json里Windows 配置有个webviewInstallMode字段可以设置为downloadBootstrapper下载安装器引导用户安装或embedBootstrapper把安装器嵌入应用。后者会增加几 MB 体积但用户体验更顺畅。我建议默认用downloadBootstrapper只有在需要完全离线的场景才用嵌入。5.2 Rust 编译慢和增量编译的优化Tauri 项目最劝退新人的就是首次编译动不动就是几分钟到十几分钟。我自己的体验是首次编译 5~8 分钟很正常之后增量编译 30~60 秒。如果你觉得太慢可以做几个优化第一在Cargo.toml里开启优化配置但只在releaseprofile 下启用开发模式下保持默认这样开发时编译更快发布时体积更小、运行更快。第二把 Rust 依赖拆分成 workspace 成员把不常改的部分预编译成动态库减少每次改代码后的重编范围。不过这个对这个规模的桌面应用来说有点过度设计普通项目不用搞。第三合理使用sccache做编译缓存尤其是团队多人协作时效果很可观。安装sccache后在环境变量里设置RUSTC_WRAPPERsccache就行之后第二次编译会明显变快。5.3 IPC 通信的序列化开销和参数命名问题Tauri 的命令调用走的是 WebView 和 Rust 之间的桥接每次调用都有序列化和反序列化的开销。如果你高频调用比如在循环里每帧读取某个系统状态性能会不如 Rust 直接同步处理。我的经验是把高频操作聚合成一个命令在 Rust 端批量处理后一次性返回给前端而不是在 JavaScript 里反复 invoke。参数命名也是高频翻车点。前面提到过前端调用的驼峰参数会自动转换成 Rust 的蛇形参数但这个转换是有边界的。如果你前端传了{ user-name: x }Rust 参数名却叫user_nameTauri 默认不会做这种中划线到蛇形下划线的转换会报参数不存在。最好统一命名风格前端全用驼峰Rust 全用蛇形别混用。5.4 Linux 打包时缺失 WebKitGTK 依赖在 Linux 上跑tauri build如果系统没装libwebkit2gtk-4.1-dev编译会直接报webkit2gtk-4.1-sys找不到库之类的错误。不同发行版包名不一样Debian/Ubuntu 用libwebkit2gtk-4.1-devFedora 用webkit2gtk4.1-develArch 用webkit2gtk-4.1。这个坑在官方文档里有写但很多人习惯先跑命令再查文档结果浪费了不少时间。还有一个小坑如果你用 Docker 或 CI 环境构建 Linux 包容器里可能没有图形库而 Tauri 编译时需要libgtk-3-dev和libayatana-appindicator3-dev。记得在 Dockerfile 里提前装好否则编译到一半才报错特别影响心情。5.5 Electron 项目的内存治理和 GC 调优其实是两套思路说到这得补一句反方向的经验。我这次迁移之后又看了一眼还在用 Electron 跑的另一套老系统发现它的内存问题不光靠“换壳”能解决。Electron 里有一个非常好用但常被忽略的 APIapp.getAppMetrics()能拿到每个进程的 CPU、内存、PID 数据配合启动参数--expose-gc可以在主进程里手动触发垃圾回收定时判断当前打包软件占用的内存再根据阈值决定是否调global.gc()清理。这种方案的本质是在“不换壳”的前提下做内存治理适合那些短期没法迁走、但内存吃紧的 Electron 存量应用。但它的天花板也很明显GC 只能回收 V8 堆里的垃圾页面里创建的 DOM 引用、WebSocket 连接、Chromium 内部的缓存这些你不主动释放GC 也帮不上忙。所以我后来的结论是存量 Electron 项目可以先靠app.getAppMetrics和定时 GC 做急诊但根治还是要靠换更轻的底座。5.6 Vue 里播放 m3u8 免安装的另一个隐藏问题跨域与鉴权接前面 3.7 提到的 m3u8 播放问题再补充一个隐藏雷区如果 m3u8 列表里的分片地址是相对路径而你的播放器页面在 WebView 的http://tauri.localhost域下浏览器会认为这是跨域请求分片加载会被拦截。Electron 里设置过webSecurity: false的话不会有这个问题但 Tauri 默认是开启安全限制的。解决方案有三种一是前端用 hls.js 时开启pLoader自定义加载器把每个请求的 header 和 CORS 模式都统一处理二是在 Rust 端写一个代理命令让 Rust 去拉取 m3u8 和 ts 分片再以字节流返回给前端三是在tauri.conf.json里配置security.csp放开相关资源的域名白名单。第一种最灵活第二种最安全但性能差点第三种最省事但 CSP 配得不好会影响其他资源加载。我项目里最后用方案一因为播放的源地址是动态的CSP 白名单不好提前写死。6. 除了 Tauri还有哪几个值得关注的方向Rust on the Desktop 的想象力6.1 egui 和 iced不需要 WebView 的 Rust 原生生力军很多人对 Rust 桌面开发的认知只停留在“给前端套壳”Tauri其实 Rust 原生的 GUI 框架这两年发展也很快。比如egui一个即时模式的 GUI 库整个界面完全用 Rust 代码绘制不依赖 WebView、不依赖系统控件打包出来非常小内存占用也低。如果你想做一个工具型、数据密集型、对 UI 美观度要求不高的桌面应用egui 的学习曲线不算陡性能表现比 WebView 方案更稳定。iced则更像 Elm 架构的 Rust 版适合写结构清晰、状态管理严格的桌面应用。它的热重载和声明式 UI 体验和 Web 前端很接近如果团队里有人写过 React 或 Vue上手会很快。不过必须客观说这类框架的成熟度目前还远不如 Tauri/Electron。复杂表单、富文本、视频嵌入、系统级交互等场景下你得手写大量底层代码开发效率远低于 Web 方案。我的判断是如果应用是纯工具型、界面简单、性能要求极高可以尝试 egui如果应用有大量复杂交互、图表、富文本还是 WebView 方案更省力。6.2 Rust 的业务价值不止在桌面壳更在核心模块Tauri 的另一个隐藏价值在于它让前端团队可以“渐进式地引入 Rust”。你不一定把整个应用都换成 Rust但可以把性能敏感的模块、加解密逻辑、图像处理、复杂算法拆成独立 crates然后通过 Tauri command 暴露给前端调用。这样一来不需要重构整个应用就能在关键路径上获得原生的性能收益。我现在这个项目就是这种模式界面和大部分业务逻辑还是 Vue 写的但文件解析、数据校验、批量计算这些高频 CPU 密集任务都挪到了 Rust 侧。实测下来批量处理一个几千行的配置文件原来在 Electron 里要 3 秒现在 Tauri 里不到 0.5 秒而且内存峰值下降了 60%。这种收益是单纯的“换壳”给不了的也是 Rust 在桌面领域真正的想象空间。7. 写在最后的实在话和后续可以继续做的事情说实话做完这次迁移和横评我对桌面开发的选型思路有了一个很大的转变。以前拿到一个“要做个桌面端”的需求第一反应就是 Electron因为它能让我最快把 Web 能力搬到桌面但现在我第一反应是先问自己这个应用真的需要一个浏览器内核吗如果只是表单、图表、表格、文件操作Tauri 完全能胜任如果涉及大量媒体处理、复杂的系统级 API那 Electron 可能更省心。我个人实际操作的体会是Tauri Vue 的技术栈特别适合三类人一是被 Electron 体积和内存折磨过、想换一条路的前端团队二是对 Rust 有基础的独立开发者想做出轻量且高性能的工具型应用三是已经在 Electron 上做了一版原型想进一步压缩发布体积和运行时开销的项目。最后再分享一个小技巧如果你也在做 Tauri 迁移先把 Electron 里的main进程逻辑和renderer逻辑彻底厘清尤其注意 main 进程里那些直接操作 Node.js API 的代码这些就是迁移的主要工作量所在。把所有 Node 依赖和系统调用列成一个清单逐个对照 Tauri 插件或自定义 Rust command 方案去替换迁移会顺利很多。这篇文章没有涵盖 Tauri 的多窗口管理、无边框窗口和系统托盘这些扩展点后续我会再单独写一篇把窗口定制和更新机制补完。如果你正在评估桌面方案或者已经开始动手迁移欢迎带着具体问题来交流很多坑光看文档是发现不了的得踩过一遍才知道。
返回列表