Wails v3.0.0 发布:窗口和托盘变成显式对象,v2 项目要按新运行时重写
Wails 让 Go 程序员用已有的 Web 前端工具写桌面应用,渲染层用各平台原生 WebView 而不是打包一个浏览器。后端是 Go,界面是 HTML/CSS/JS 或任意前端框架,最终封装成单个原生应用。
- 官网:https://wails.io
- v3 文档:https://v3.wails.io/
- v2 → v3 迁移指南:https://v3.wails.io/migration/v2-to-v3/
- 仓库:https://github.com/wailsapp/wails
v3.0.0 发布于 2026 年 10 月 26 日,使用 Go 1.26 构建。
v3 的对象模型:应用、窗口、服务、事件
v2 是单窗口、context 驱动的运行时,日常桌面开发里很多事做起来比应有的更麻烦。v3 把应用、窗口、服务、事件和平台能力都变成显式对象:创建 application、注册 service、创建 window,然后与持有该行为的对象通信。
v3.0.0 包含的能力:
- 多窗口:运行时创建、管理、关闭,每个窗口有自己的配置和生命周期。
- 系统托盘:菜单、亮/暗图标、macOS 的 template icon,可把窗口附着到托盘图标。
- 原生菜单和对话框。
- 服务与绑定生成:后端仍是普通 Go;绑定通过静态源码分析生成,注释和参数名会带到前端,命令是
wails3 generate bindings。 - 基于 Taskfile 的构建系统:可查看、扩展、调试。
- 跨平台:Windows amd64/arm64,macOS Intel/Apple Silicon,Linux amd64/arm64,默认 GTK4 + WebKitGTK 6.0;旧 GTK3 栈通过
-tags gtk3保留到 v3.1。 - iOS/Android 实验性支持:共用同一个
main.go和前端。 - 应用内更新器:可插拔 provider、加密校验、原子替换、默认 UI。
- 打包与签名指南,以及 server build(不开原生窗口,把同一应用和服务当 HTTP server 跑)。
beta 之后的变化:文档站换到 M-Press;Windows 上 WebView2 进程挂掉后能恢复,不再留白窗;全局快捷键尊重键盘布局(AZERTY、QWERTZ、Dvorak);更新器针对 Linux 跨文件系统替换和 AppImage 做了加固;wails3 setup 向导完成;wails3 dev 退出时会停掉后台进程;macOS 26+ 使用原生 Liquid Glass,并有 fallback。
安装与初始化:
go install github.com/wailsapp/wails/v3/cmd/wails3@v3.0.0
wails3 setup
wails3 init
模板有 vanilla、React、Vue、Svelte,均提供 JS 或 TS 版本。
Windows / Linux 运行时上的实际坑
v3.0.0 修复的几个问题都集中在平台运行时:
- Windows 绘制菜单栏时崩溃
panic: SetTextColor failed(#6311)。 - Windows 上
pkg/w32初始化卸载了uxtheme.dll导致applyDarkMode崩溃(#6356)。 wails3 update cli找不到 v3 的发布,因为它只考虑 v2 的 tag。- 重启待定时 staged update 的安全性;替换前校验 staged payload、丢弃备份前先校验已安装应用,损坏的更新会回滚。
Linux 侧要注意默认栈已经切到 GTK4 + WebKitGTK 6.0,只有显式加 -tags gtk3 才走旧栈,而这个开关只保留到 v3.1。
安全公告与已知限制
安全修复:Linux(GTK3/GTK4)上拦截来自跨源子 frame 的保留 wails: 消息,做法是向所有 frame 注入 guard 脚本,缓解 GHSA-2p5f-2gx8-mh8m。同时把 klauspost/compress 升到 1.18.7、golang.org/x/image 升到 0.45.0,并用 Go 1.26.10 构建以获得 crypto/x509 修复(GO-2026-6809);runtime 包、wizard、示例和模板里的 vite 升到 8.2.4+(对应六个 GHSA)。
已知限制:
- Linux:guard 无法阻止同源子 frame(
srcdoc或about:blankiframe)通过父级触达 native message handler,因为 WebKitGTK 不向 handler 提供 frame 信息。跨源 frame 和未开启allow-same-origin的 sandboxed frame 会被拦住。不要嵌入不可信的同源内容。 - Android(实验性):
window.wailsbridge 暴露给 WebView 中的每个 frame,没有 main-frame 或 origin 检查。计划在 3.0.1 修复。 - 所有平台:子 frame 调用绑定方法走的是 HTTP 到
/wails/runtime,不经过 native message handler,所以 guard 不限制这类调用。任何被嵌入的 iframe 都应视为拥有已绑定 Go 方法的访问权限。
官网给出的对比数据:二进制约 15MB(Electron 约 150MB),基线内存约 10MB,启动 <0.5s,不开端口、走内存 IPC。
从 v2 迁移:不是升版本号,是移植
主要变化有四处:应用与窗口生命周期;用 service 取代绑定在 context 上的 binding;用 application/window 的直接 API 取代 v2 的 runtime 包;前端绑定需要重新生成。v2 仍会收到关键更新,两个 CLI 是独立的二进制(wails 和 wails3),模块导入路径也不同。
启动方式对照:
// v2:单窗口,Bind 传服务实例
err := wails.Run(&options.App{
Title: "My App",
Width: 1024,
Height: 768,
Bind: []interface{}{&GreetService{}},
})
// v3:应用 + 服务 + 窗口分开创建
app := application.New(application.Options{
Name: "My App",
Services: []application.Service{
application.NewService(&GreetService{}),
},
})
app.Window.NewWithOptions(application.WebviewWindowOptions{
// 窗口参数
})
app.Run()
服务写法也变了:v2 要求在结构体里放 context 字段并在 startup(ctx) 里接收;v3 用 service 模式,由框架注入 app 依赖。
运行时 API 从全局函数改为对象方法:v2 通过 runtime 包的全局函数并传入 ctx 操作窗口、发事件;v3 直接在 app/window 对象上调用,例如 window.SetTitle、app.Event.Emit。
生成的绑定落在 bindings 目录,按应用名和服务名组织。
发布节奏
- nightly:
vX.Y.0-nightly.YYYYMMDD - 每周一个 minor:
v3.1.0 - hotfix:补丁版本
@latest 始终解析到 weekly/hotfix,不会指向 nightly。@wailsio/runtime 的 npm 版本与发布版本一致,项目模板会固定 runtime 版本。