Wails:Go 语言挑战 Electron,赌上桌面级应用之未来

BBetter Stack
컴퓨터/소프트웨어AI/미래기술

Transcript

00:00:00Wails 是一项跨平台技术,能让你用 Go 语言构建桌面级应用。
00:00:04在我制作了几期桌面框架对比视频后,频道里有很多观众一直在敲碗这期内容。
00:00:08所以今天,我将带大家体验如何用 Wails 构建桌面级应用,
00:00:13并将其与 Electron 和 Tauri 等框架进行对比。我们将动手开发一个
00:00:17桌面录屏工具(之前视频也做过类似的),并对比文件体积、
00:00:22性能以及开发者体验。对我来说 Wails 也是个全新的东西,
00:00:27所以这次我们边学边看。Wails 的运行机制和 Tauri 非常相似,
00:00:36但后端使用的是 Go 而非 Rust。你依然是用 Web 技术在 WebView 中构建前端,
00:00:41然后调用由 Golang 管理的原生 API。这意味着你能编译出同时兼容
00:00:47Mac 和 Windows 的应用程序。不过与 Electron 不同的是,Wails 并未内置浏览器。
00:00:52相反,它像 Tauri 一样复用每个平台原生的渲染引擎。因此打包后的体积
00:00:58理论上打包体积应该小得多,但我们稍后在进行对比时会具体看看。
00:01:03如果你喜欢此类内容,别忘了点个订阅。这就是我
00:01:07用 Wails 开发的录屏工具,之前我也用 Electron 和 Tauri 实现过同样的软件。
00:01:12我们选择要录制的目标屏幕,点击录制。你可以随意移动鼠标,软件本身的界面
00:01:16并不会被录进去。点击停止后,就能直接预览刚才录制好的画面。
00:01:21需要的话还可以进行剪辑,最后点击导出为 MP4,就能把视频直接
00:01:27保存到本地。看一下这个项目的目录结构,你会发现它和
00:01:32Electron 的常见结构非常相似。所有前端文件都在 frontend 文件夹里,
00:01:36然后有一个入口文件。在这里是一个名为 main.go 的 Go 文件,
00:01:41里面包含一个 main 函数。这和 Electron 中的设计基本一致,我们可以
00:01:47在里面声明窗口标题、宽高、背景颜色,甚至能单独配置
00:01:52针对 Mac 的专属选项。如果你想区分 Mac 和 Windows 的逻辑,这完全可行。
00:01:57现在看回 frontend 目录下的 source 文件夹,你会看到所有的
00:02:02React 代码。打开 App.tsx,这就是非常标准的 React 代码,除了
00:02:09我们在里面调用了在 Go 端定义的 API。看下这个名为 API 的导入项目,追踪它在文件里的调用,
00:02:16可以看到我们调用了 API.onrecording finished、onrecording failed、start recording,而这个 API 模块
00:02:22是由 Wails 自动生成的。如果打开 API 文件本身,会发现所有核心
00:02:27函数都来自 wails.js/go/main/App 这个路径。深入看
00:02:33这个文件,你会发现它完全是自动生成的,顶部还有威尔士语和英语的注释,
00:02:39信不信由你,这是因为 Wails 的作者就是威尔士人。这里包含了像
00:02:43export video、list sources、request screen access 等所有录屏工具所需的功能函数。
00:02:49现在如果我们切到 Go 端的 app.go 文件,尝试把
00:02:54list sources 注释掉并保存,你会发现 API.ts 里面立刻抛出了错误,因为
00:02:59此时 list sources 不存在了。这是因为我们运行着 wails dev 命令,只要
00:03:05Go 文件发生变化,它就会自动重新生成 TypeScript 的类型定义。现在回到 Go 文件
00:03:11把代码取消注释,错误提示瞬间就消失了,桌面应用也自动重载,
00:03:16因为来自 Go 侧(即后端)的所有修改,都会触发应用的自动增量编译和界面渲染。
00:03:23接下来我们做几项横向对比,看看这三大框架之间的实际差距。
00:03:27首先是打包体积:Wails 为 52 MB,Tauri 为 57 MB,而 Electron
00:03:34毫不意外地达到了 324 MB。Wails 和 Tauri 优势极其明显,原因在于它们
00:03:41没有内置 Chromium 浏览器,这符合预期。不过我也要指出,直接使用各平台原生
00:03:47WebView(即 Wails 和 Tauri 的做法)更容易在不同操作系统间遇到渲染差异。
00:03:51虽然如今这种兼容性问题少多了,但仍需留个心眼。总体来说,Tauri 和
00:03:57Wails 打包出的产物在体积上非常接近,因为尽管底层技术栈完全不同,
00:04:02但这两个框架的整体架构设计几乎如出一辙。
00:04:07再来看看启动时间。跟以往的桌面框架测试一样,我们将
00:04:12每个应用分别冷热启动 10 次取平均值。热启动下:Wails 为 395
00:04:18毫秒,Tauri 为 410 毫秒,Electron 为 350 毫秒。而在每次都清除缓存的
00:04:26冷启动测试中:Wails 为 2337 毫秒,Tauri 为 2049 毫秒,Electron 实际上反而稍微领先,
00:04:34成绩为 1890 毫秒。再看运行时性能:与 Tauri 类似,Wails 在屏幕录制时的
00:04:40运行时性能远优于 Electron。这主要归功于架构设计:我们直接调用了
00:04:45Mac 原生的 ScreenCaptureKit,数据无需经过 IPC 桥接;而 Electron 则是直接从
00:04:51WebView 内部截取画面再传输给后端,这必然会带来额外的开销。
00:04:56技术上说,如果你为 Electron 编写自定义 C 代码,也是能用到原生 ScreenCaptureKit 的,
00:05:02但前者才是 Electron 的默认开发姿势,因此我们今天基于默认方案做对比。
00:05:06最后谈谈开发者体验(DX),这也是差异最悬殊的地方。
00:05:11我个人非常享受用 Wails 开发的过程,但必须指出,实现屏幕捕获这块
00:05:15并没有 Tauri 那么简单轻松。我不得不手写 Objective-C 代码去对接 ScreenCaptureKit,
00:05:21而在 Tauri 中你可以全程只写 Rust。这是因为 Rust 拥有庞大的生态,
00:05:28社区提供了很多封装好的 Apple 原生框架 crate 库。在 Tauri 里我直接引入一个叫 screen-capture-kit
00:05:33的 crate,整套录屏 API 就全是标准的 Rust 代码。而在 Go 生态里,我没找到任何成熟好用的
00:05:39ScreenCaptureKit 封装,不过它有 Cgo,也就是 Go 内置编译 C 代码的功能。
00:05:44这意味着在 Go 里,你可以直接在 .m 文件中编写原生 C/OC,将其暴露为纯 C 函数,
00:05:50再告诉 Go 去链接 Apple 的哪个系统框架。这样一来,你实际上是在写真正的 Objective-C
00:05:56去调用和 Rust crate 完全一样的 Apple API,只不过这次底层代码全在你掌控之中。
00:06:02最终这多出了大约 450 行 Objective-C 代码,而 Rust 版完全不需要写这些。所以综合来看,
00:06:08我个人稍微更偏向 Tauri 一些。就我目前的体验来看,Rust 的生态生态圈更完善,
00:06:14但说到底这取决于你的偏好。如果你喜欢用 Go 开发,Wails 绝对是极其
00:06:18优秀的选择;如果你青睐 Rust,直接选 Tauri 就好。不过如果选择 Wails,你可能需要
00:06:24做好手写部分原生代码的准备,毕竟它的生态还没那么成熟。希望大家喜欢本期视频,
00:06:29欢迎订阅以获取更多同类内容。如果你想看更多桌面框架的对比视频,
00:06:33比如我们之前对比 Deno Desktop 和 Electrobun 的那一期,我把视频链接
00:06:39放在了这里,点击即可观看。非常感谢大家的收看,我是来自 BetterStack 的 Warren,
00:06:43我们下期再见!另外不幸的是,Milo(小狗)说这周不能再录视频了,
00:06:49所以我们周一见。
00:06:50*背景音乐*

Key Takeaway

Wails 凭借无内置浏览器的架构实现了 52 MB 的超小打包体积与优异的运行时录屏性能,但在调用 macOS 原生 API 时因生态尚未成熟而需要借助 Cgo 手写 Objective-C 代码。

Highlights

  • Wails 打包体积仅为 52 MB,与 Tauri 的 57 MB 相近,远小于 Electron 的 324 MB。

  • 在冷启动测试中,Electron 以 1890 毫秒领先,Wails 为 2337 毫秒,Tauri 为 2049 毫秒。

  • 热启动表现下 Wails 耗时 395 毫秒,Tauri 为 410 毫秒,Electron 为 350 毫秒。

  • Wails 运行 wails dev 命令时,Go 端的 API 修改会自动同步生成 TypeScript 类型定义并实时重载应用。

  • 由于 Go 生态缺乏现成的 ScreenCaptureKit 封装,Wails 开发录屏功能需要通过 Cgo 手写约 450 行 Objective-C 原生代码。

Timeline

Wails 的核心架构与技术原理

  • Wails 结合 Go 后端与 Web 前端渲染构建跨平台桌面应用。
  • Wails 放弃内置浏览器,改为复用系统原生的 WebView 渲染引擎。
  • 原生 WebView 复用架构显著降低了应用打包产物的体积。

Wails 的工作运行机制与 Tauri 高度相似,主要区别在于后端采用 Go 语言而非 Rust。前端依然使用 Web 技术栈,通过自动生成的接口调用 Go 管理的原生 API,支持同时编译出 macOS 与 Windows 应用。由于没有内置 Chromium 浏览器,应用体积大幅缩减。

项目结构与类型自动生成机制

  • Wails 的目录结构划分清晰,前端 React 代码集中于 frontend 目录,Go 入口位于 main.go。
  • Wails 提供增量编译与热重载,Go 侧代码变更会自动触发 TypeScript 类型文件重构。

应用主入口 main.go 负责配置窗口标题、尺寸、背景色及平台专属选项。前端通过绑定 Go 端 App 结构体暴露出原生函数,在运行 wails dev 开发命令时,Go 端函数的任何改动都会同步更新 API.ts 中的类型声明并触发应用增量重载。

体积、启动速度与运行时性能对比

  • Wails 和 Tauri 包体积均在 50-60 MB 左右,仅为 Electron 的六分之一。
  • 启动速度方面,Electron 在冷热启动指标上均略微领先 Wails 与 Tauri。
  • Wails 直接调用 ScreenCaptureKit,运行时录屏开销显著低于 Electron 的 WebView 截图方案。

打包体积上 Wails(52 MB)与 Tauri(57 MB)优势巨大,而 Electron 高达 324 MB。冷启动 10 次平均测试中 Electron 耗时 1890 毫秒,Wails 耗时 2337 毫秒,Tauri 耗时 2049 毫秒。但在运行时性能上,Wails 与 Tauri 直连 Mac 原生 API 数据通道,避开了 Electron 从 WebView 抓取画面的 IPC 传输开销。

开发者体验与底层生态现状

  • Rust 拥有成熟的 screen-capture-kit crate,而 Go 生态缺乏相关封装。
  • Wails 开发者需利用 Cgo 机制在 .m 文件中手写 Objective-C 代码来对接 Apple 原生 API。

在实现屏幕捕获功能时,Tauri 能够直接引入现成的 Rust crate 库,全流程使用 Rust 开发。Wails 则需要借助 Go 的 Cgo 功能,手动编写约 450 行 Objective-C 原生代码并链接系统的 ScreenCaptureKit 框架。因此,偏好 Go 的开发者可以使用 Wails,但需做好手写底层原生代码的准备。

Community Posts

View all posts