参与贡献

编辑此文档

翻译文档,或在您的计算机上打开完整项目。

在您选择提交工作成果之前,不会发布任何内容。

Wails 的工作原理

了解 Wails 的架构及其如何实现原生性能

Wails 是一个桌面应用程序开发框架,使用Go 构建后端,并使用Web 技术构建前端。但与 Electron 不同,Wails 不会捆绑浏览器,而是使用操作系统的原生 WebView。

Wails 应用, 前端, Go 后端, 操作系统, 初始化, 提供静态 Web 应用, 通过操作系统原生 WebView 渲染站点, 常规通信, 发起 API 风格的调用, 服务处理请求, 生成响应, 处理响应

与 Electron 的主要区别:

方面 Wails Electron
浏览器 操作系统提供的 WebView 捆绑的 Chromium(约 100MB)
后端 Go(编译执行) Node.js(解释执行)
通信 内存桥接 IPC(进程间通信)
包体积 约 15MB 约 150MB
内存 约 10MB 约 100MB+
启动时间 <0.5 秒 2-3s

核心组件

1. 原生 WebView

Wails 使用操作系统内置的 Web 渲染引擎:

WebView2(Microsoft Edge WebView2)

  • 基于 Chromium(与 Edge 浏览器相同)
  • 预装在 Windows 10/11上
  • 通过 Windows Update 自动更新
  • 全面支持现代 Web 标准

这为何重要:

  • 不捆绑浏览器 → 应用体积更小
  • 操作系统原生 → 集成度和性能更好
  • 自动更新 → 通过操作系统更新获取安全补丁
  • 熟悉的渲染效果 → 与系统浏览器一致

2. Wails 桥接器

桥接器是 Wails 的核心,它支持 Go 与 JavaScript 之间的直接通信。

前端(JavaScript), Wails 桥接层, JSON 编码器, 方法路由器, JSON 解码器, 后端(Go), 已注册的服务

工作原理:

  1. 前端调用 Go 方法(通过自动生成的绑定)
  2. 桥接器将调用编码为 JSON(方法名 + 参数)
  3. 路由器在已注册的服务中查找 Go 方法
  4. Go 方法执行并返回值
  5. 桥接器解码结果并将其发回前端
  6. JavaScript 中的Promise 使用该结果完成兑现

性能特征:

  • 内存通信:无网络开销,不使用 HTTP
  • 尽可能实现零拷贝(适用于大型数据)
  • 默认异步:两端均不阻塞
  • 类型安全:自动生成 TypeScript 定义

3. 服务系统

服务是向前端公开 Go 功能的推荐方式。

go
// Define a service (just a regular Go struct)
type GreetService struct {
    prefix string
}

// Methods with exported names are automatically available
func (g *GreetService) Greet(name string) string {
    return g.prefix + name + "!"
}

func (g *GreetService) GetTime() time.Time {
    return time.Now()
}

// Register the service
app := application.New(application.Options{
    Services: []application.Service{
        application.NewService(&GreetService{prefix: "Hello, "}),
    },
})

服务发现:

  • Wails 在启动时扫描你的结构体
  • 导出的方法可由前端调用
  • 提取类型信息以生成 TypeScript 绑定
  • 错误处理会自动完成(Go 错误 → JS 异常)

生成的 TypeScript 绑定:

typescript
// Auto-generated in frontend/bindings/GreetService.ts
export function Greet(name: string): Promise<string>
export function GetTime(): Promise<Date>

为什么使用服务?

  • 类型安全:完整支持 TypeScript
  • 自动发现:无需手动注册方法
  • 组织有序:将相关功能归为一组
  • 可测试:服务只是 Go 结构体

详细了解服务 →

4. 事件系统

事件支持组件之间进行发布/订阅通信。

Wails 事件系统, 窗口 1, 窗口 2, Go 后端, 事件驱动器, 订阅 'data-updated' 事件, 订阅 'data-updated' 事件, 应用发出 Emit('data-updated', data), 订阅者通过 On('data-updated', handler) 处理, 订阅者通过 On('data-updated', handler) 处理

用例:

  • 窗口通信:一个窗口通知其他窗口
  • 后台任务:Go 服务向 UI 通知进度
  • 状态同步:使多个窗口保持同步
  • 松耦合:组件无需直接引用彼此

示例:

go
// Go: Emit an event
app.Event.Emit("user-logged-in", user)
javascript
// JavaScript: Listen for event
import { Events } from '@wailsio/runtime'

Events.On('user-logged-in', (user) => {
    console.log('User logged in:', user)
})

详细了解事件 →

应用生命周期

了解生命周期有助于确定何时初始化和清理资源。

应用启动, 初始化, 创建应用, 注册服务, 设置窗口/菜单, 事件循环, 处理事件, 处理消息, 更新 UI, 关闭, 清理资源, 保存状态, 应用结束

生命周期钩子:

go
app := application.New(application.Options{
    Name: "My App",

    // Cleanly intercept quit requests (e.g. unsaved changes).
    ShouldQuit: func() bool { return true },

    // Called when the app is confirmed to be quitting — save state, close connections, etc.
    OnShutdown: func() {},
})

application.Options上没有OnStartup字段。启动工作应放在服务的ServiceStartup(ctx, options)中、通过app.Event.OnApplicationEvent(events.Common.ApplicationStarted, ...)注册的回调中,或者直接放在app.Run()之前。

详细了解生命周期 →

构建流程

了解 Wails 如何构建应用:

源代码, Go 代码 (main.go, 服务), 前端代码 (HTML/CSS/JS), 构建流程, 分析 Go 代码, 生成绑定, 构建前端, 编译 Go 代码, 嵌入资源, 输出, 原生二进制文件 (myapp.exe/.app)

构建步骤:

  1. 分析 Go 代码
  • 扫描服务中的导出方法
  • 提取参数类型和返回类型
  • 生成方法签名
  1. 生成 TypeScript 绑定
  • 为每个服务创建.ts文件
  • 包含完整的类型定义
  • 添加 JSDoc 注释
  1. 构建前端
  • 运行打包工具(Vite、webpack 等)
  • 缩小并优化
  • 输出到frontend/dist/
  1. 编译 Go
  • 启用优化进行编译(-ldflags="-s -w")
  • 包含构建元数据
  • 针对特定平台进行编译
  1. 嵌入资源
  • 将前端文件嵌入 Go 二进制文件
  • 压缩资源
  • 创建单个可执行文件

结果:一个嵌入了所有内容的原生可执行文件。

详细了解构建 →

开发环境与生产环境

Wails 在开发环境和生产环境中的行为有所不同:

特性:

  • 热重载:前端更改会立即重新加载
  • 源映射:使用原始源代码进行调试
  • DevTools:可使用浏览器 DevTools
  • 日志记录:启用详细日志记录
  • 外部前端:由开发服务器(Vite)提供

工作原理:

Wails 应用, Vite 开发服务器 (localhost:5173), WebView

优势:

  • 立即获得更改反馈
  • 完整的调试能力
  • 更快地迭代

内存模型

了解内存使用情况有助于构建高效的应用程序。

内存区域:

  1. Go 堆
  • 服务和应用程序状态
  • 由 Go 垃圾回收器管理
  • 简单应用程序通常为 5-10MB
  1. WebView 内存
  • DOM、JavaScript 堆、CSS
  • 由 WebView 引擎管理
  • 简单应用程序通常为 10-20MB
  1. 桥接层内存
  • 用于通信的消息缓冲区
  • 开销极小(<1MB)
  • 尽可能对大型数据采用零拷贝

优化建议:

  • 避免传输大量数据:传递 ID,按需获取详细信息
  • 使用事件进行更新:不要从前端轮询
  • 以流式方式处理大文件:不要将整个文件加载到内存中
  • 清理监听器:使用完毕后移除事件监听器

详细了解性能 →

安全模型

Wails 提供默认安全的架构:

前端(不受信任), Wails 桥接层(验证), 后端(受信任)

安全功能:

  1. 方法白名单
  • 只能调用已导出的方法
  • 无法访问私有方法
  • 必须显式注册服务
  1. 类型验证
  • 根据 Go 类型检查参数
  • 拒绝无效类型
  • 防止注入攻击
  1. 不使用 eval()
  • 前端无法执行任意 Go 代码
  • 只能调用预定义的方法
  • 不执行动态代码
  1. 上下文隔离
  • 每个窗口都有自己的上下文
  • 服务可以检查调用方上下文
  • 可以为每个窗口设置权限

最佳实践:

  • 在 Go 中验证用户输入(不要信任前端)
  • 使用上下文进行身份验证和授权
  • 执行文件操作前清理文件路径
  • 对开销较大的操作实施速率限制

详细了解安全性 →

后续步骤

应用程序生命周期 - 了解启动、关闭和生命周期钩子 了解更多 →

Go-前端桥接 - 深入了解桥接的工作原理 了解更多 →

构建系统 - 了解 Wails 如何构建应用程序 了解更多 →

开始构建 - 在教程中运用所学知识 教程 →


对架构有疑问?请前往 Discord 提问,或查阅API 参考。

编辑页面

最后更新: