编程 Wails v3.0.0 发布:窗口和托盘变成显式对象,v2 项目要按新运行时重写

2026-10-31 21:01:13

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:blank iframe)通过父级触达 native message handler,因为 WebKitGTK 不向 handler 提供 frame 信息。跨源 frame 和未开启 allow-same-origin 的 sandboxed frame 会被拦住。不要嵌入不可信的同源内容。
  • Android(实验性):window.wails bridge 暴露给 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 版本。

复制全文 生成海报 Go Wails 桌面应用 WebView 版本升级

推荐文章

程序员茄子在线接单