Wails3 项目模板上手指南:从wails3 init到开发与生产构建的完整实战
【免费下载链接】wailsCreate beautiful applications using Go项目地址: https://gitcode.com/gh_mirrors/wa/wails
本篇技术指南围绕 Wails v3 内置模板体系展开:每个新建项目都会在根目录生成一份 README.md,它既是项目模板的核心骨架,也是你理解 Wails3 项目结构、开发命令与后续扩展路径的第一手文档。读完本文,你将掌握 Wails3 项目的目录构成、wails3 dev热重载与wails3 build生产构建的正确用法,并能基于内置示例与模板源码(templates.go)理解整个脚手架机制,具备自行创建自定义模板的能力。
Wails3 项目脚手架:模板体系与_common共享层
在 Wails v3 中,wails3 init创建项目时并不直接写死目录结构,而是从一个内置模板仓库(v3/internal/templates)中抽取内容。该目录下包含base/、vanilla/、vue/、react/、svelte/等前端框架模板,以及一个特殊的_common/共享目录。
_common是所有内置模板公用的骨架层,存放 Go 后端、任务定义与模块文件,例如:
- main.go.tmpl:应用入口模板;
- greetservice.go:示例绑定服务;
- Taskfile.tmpl.yml:构建/开发任务定义;
- go.mod.tmpl 与 go.sum.tmpl:Go 模块文件;
- README.md:生成项目的欢迎文档;
- gitignore.tmpl:生成
.gitignore; frontend/:前端公共资源(背景图、字体许可、npmrc)。
从源码可以看到,模板安装流程(templates.go)会先把_common目录整体抽出,再叠加所选框架模板的内容:
common, err := fs.Sub(templates, "_common") // ... err = gosod.New(common).Extract(options.ProjectDir, templateData) // ... err = gosod.New(tfs).Extract(options.ProjectDir, templateData)以_开头的目录会被模板注册逻辑自动跳过(templates.go),不会作为独立模板暴露,但它会通过fs.Sub嵌入到每一个实际模板中。这正是“所有内置模板共享同一份 Go 后端骨架”的实现基础。
创建项目与模板元数据
选择模板
可用模板由wails3 init -l列出,其来源有三种(templates.go):
- 内置模板:
vanilla、vue、react、svelte等,由init()扫描嵌入的模板目录自动注册; - 本地模板:直接传一个包含
template.yaml的目录路径; - 远程模板:传一个 Git 仓库 URL,可带
@tag指定版本,安装时自动git clone到临时目录(templates.go)。
每种模板都通过 template.yaml 声明元数据,例如内置的 vanilla 模板:
# yaml-language-server: $schema=https://v3.wails.io/schemas/template.v3.json name: "Vanilla + Vite (TypeScript)" shortname: vanilla author: Lea Anthony description: "Vanilla + TypeScript + Vite — the default template" helpurl: https://wails.io version: v0.0.1 wailsVersion: 3 typescript: true其中wailsVersion: 3是必填项,解析器会拒绝任何非 3 的版本(templates.go);typescript: true让模板生成器为前端生成 TypeScript 绑定(绑定风格可选 Class 或 Interface,见 templates.go)。
模板变量
.tmpl后缀文件在wails init时由模板引擎处理,以下变量会在生成项目时被替换为实际值:
| 变量 | 含义 |
|---|---|
{{.ProjectName}} | 用户通过-n指定的项目名 |
{{.ModulePath}} | Go 模块路径(-mod指定或由-git推导) |
{{.WailsVersion}} | 生成项目所用的 Wails 版本 |
{{.BinaryName}} | 由项目名规范化的可执行文件名(小写、空格转-) |
{{.Typescript}} | 是否 TypeScript 模板 |
{{.Opn}}/{{.Cls}} | 字面量{{/}},用于在模板内安全书写 go-task 的模板语法 |
无.tmpl后缀的文件(如greetservice.go)会被原样复制。此外,wails3 generate template命令可以基于_common快速生成自定义模板骨架(templates.go)。
项目目录结构解读
新建项目后你会得到如下结构(对应 README.md 中的 Project Structure 章节):
your-project/ ├── frontend/ # 前端代码(HTML/CSS/JavaScript/TypeScript) ├── main.go # Go 后端入口 ├── app.go # 应用结构与方法定义(部分模板) ├── greetservice.go # 示例绑定服务 ├── wails.json # Wails 项目配置 ├── Taskfile.yml # 构建/开发任务 ├── go.mod / go.sum # Go 模块文件 └── build/ # 构建资产(由 init 自动生成)各关键文件的职责如下:
- main.go:应用入口。使用 Go 标准库
embed将frontend/dist嵌入二进制,创建应用与窗口,并注册 Go 服务; - frontend/:前端源码,由
wails3 dev中的 Vite 开发服务器提供热更新; - wails.json:项目级配置,描述名称、前端工具链等信息;
- Taskfile.yml:基于 go-task 的任务定义,
wails3 build、wails3 package、wails3 run均通过它分派到对应平台。
深入解析生成的 main.go:应用、窗口、服务与事件
main.go.tmpl 生成的入口展示了 Wails3 的核心编程模型,逐段解读如下。
嵌入前端资源
//go:embed all:frontend/dist var assets embed.FSfrontend/dist是前端构建产物目录,wails3 build时会先构建前端再嵌入二进制;开发模式下则由外部 dev server 提供服务。
注册类型化事件
func init() { application.RegisterEventstring }RegisterEvent声明一个数据类型为string的事件。这一步并非运行必需,但绑定生成器(wails3 generate bindings)会据此为前端生成强类型的 JS/TS API,让事件收发获得编译期检查。
创建应用
app := application.New(application.Options{ Name: "{{.ProjectName}}", Description: "A demo of using raw HTML & CSS", Services: []application.Service{ application.NewService(&GreetService{}), }, Assets: application.AssetOptions{ Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, }, })要点:
Name取自{{.ProjectName}}模板变量,即wails3 init -n传入的名字;Services将 Go 结构体实例暴露给前端,其方法会被自动生成 JS/TS 绑定;Assets通过application.AssetFileServerFS(assets)将嵌入的frontend/dist作为静态资源服务器;Mac选项配置 macOS 特有行为,例如最后窗口关闭即退出。
创建窗口
app.Window.NewWithOptions(application.WebviewWindowOptions{ Title: "Window 1", // Window sized to the golden ratio (1000 / 618 ≈ 1.618). Width: 1000, Height: 618, Mac: application.MacWindow{ InvisibleTitleBarHeight: 50, Backdrop: application.MacBackdropTranslucent, TitleBar: application.MacTitleBarHiddenInset, }, BackgroundColour: application.NewRGB(6, 7, 15), URL: "/", })窗口默认按黄金比例1000 × 618打开,背景色由application.NewRGB(6, 7, 15)指定,URL: "/"表示加载嵌入资源的根路径。MacWindow配置了 macOS 隐藏式标题栏与毛玻璃背景。
事件发射与运行
go func() { for { now := time.Now().Format(time.RFC1123) app.Event.Emit("time", now) time.Sleep(time.Second) } }() err := app.Run() if err != nil { log.Fatal(err) }后台 goroutine 每秒通过app.Event.Emit("time", now)广播当前时间;前端可用Events.On('time', ...)订阅并刷新 UI(示例见 main.js.tmpl)。app.Run()阻塞直到应用退出,错误则通过log.Fatal记录。
绑定服务示例
greetservice.go 是最小的绑定服务:
type GreetService struct{} func (g *GreetService) Greet(name string) string { return "Hello " + name + "!" }前端通过wails3 generate bindings生成的客户端调用它(如GreetService.Greet(name)),Go 返回值直接作为 Promise 结果返回,这就是“Go 后端 + Web 前端”双向通信的最小闭环。
开发模式:wails3 dev 与热重载机制
在项目根目录运行:
wails3 dev该命令会启动应用并同时开启前后端热重载:前端改动由 Vite 开发服务器即时刷新,Go 后端改动则触发重新编译与重启。
从 dev.go 的源码可以确认其端口策略:
const defaultVitePort = 9245 const wailsVitePort = "WAILS_VITE_PORT"端口优先级为:--port命令行参数 >WAILS_VITE_PORT环境变量 > 默认值9245(dev.go)。命令启动前会先探测端口占用(net.Listen失败即报错),随后:
- 把选定的端口写入
WAILS_VITE_PORT环境变量,供dev:frontend任务使用; - 按
-s是否开启 HTTPS,把FRONTEND_DEVSERVER_URL设为http://localhost:<port>或https://localhost:<port>(dev.go); - 最终调用
Watcher监视源文件变更并触发重编译(dev.go)。
生成的 Taskfile.tmpl.yml 中的dev任务与之一一对应:
dev: summary: Runs the application in development mode cmds: - wails3 dev -config ./build/config.yml -port {{.Opn}}.VITE_PORT{{.Cls}}这里的{{.Opn}}/{{.Cls}}在生成项目时会被渲染为{{/}},最终展开为{{.VITE_PORT | default 9245}},即默认 9245、可通过环境变量覆盖。
wails3 dev是直接命令,不走 Taskfile 的平台分派(这一点与build/package/run不同,相关测试见 taskfile_template_test.go)。
生产构建与运行
wails3 build
wails3 build该命令会:
- 执行前端生产构建(如 Vite
build,产物输出到frontend/dist); - 将
frontend/dist嵌入 Go 二进制; - 产出生产级可执行文件到项目
build/bin/目录(模板中BIN_DIR: "bin")。
build任务通过 Taskfile 按目标平台分派(Taskfile.tmpl.yml):
vars: GOOS: '{{.Opn}}.GOOS | default OS{{.Cls}}' tasks: build: summary: Builds the application cmds: - task: "{{.Opn}}.GOOS{{.Cls}}:build"即默认构建当前主机平台,跨平台编译时用wails3 build GOOS=windows(或设置GOOS环境变量)覆盖,随后分派到build/windows/Taskfile.yml、build/linux/Taskfile.yml等平台任务文件。此分派机制有专门测试守护(taskfile_template_test.go),确保根 Taskfile 的定制能被子任务遵守。
其他 Taskfile 任务
生成项目的根 Taskfile 还提供了一系列常用任务(Taskfile.tmpl.yml):
| 任务 | 说明 |
|---|---|
task build | 构建应用(生产) |
task package | 打包生产构建产物 |
task run | 运行应用 |
task dev | 开发模式运行 |
task install:msix:tools | 安装 Windows MSIX 打包所需工具 |
task setup:docker | 拉取交叉编译 Docker 镜像(约 800MB 下载) |
task build:server/run:server | 无 GUI 的 HTTP server 模式构建/运行 |
task build:docker/run:docker | server 模式的 Docker 镜像构建与运行 |
运行示例程序
想快速体验 Wails3 的完整能力,可进入 v3/examples 目录挑选示例,在其目录下直接运行:
go run .注意:alpha 阶段部分示例仍在开发中,个别示例可能无法直接运行。示例覆盖面很广,包括事件(events/)、窗口控制(window/)、系统托盘(systray-*)、拖放(drag-n-drop/)、通知(notifications/)、移动端(android/、ios/)等,是学习各 API 的最佳素材。
前端安全默认值与包管理
_common/frontend/npmrc为所有模板的前端设置了供应链安全默认值:
minimum-release-age=10080即拒绝安装发布不足 7 天(10080 分钟)的包版本,降低被新发布恶意包污染的风险。该配置被 pnpm 和 bun 原生支持;npm 目前会忽略它,因此这一设置对未来版本是安全且向前兼容的。
自定义模板:让团队脚手架复用到极致
理解_common的机制后,你可以通过wails3 generate template基于共享层生成自定义模板骨架(templates.go):
wails3 generate template -name mytemplate -frontend ./my-frontend生成器会:
- 把
_common内容原样复制到输出目录(模板变量保留{{.ProjectName}}等占位符,供用户后续wails init时展开); - 用
-frontend指定的目录替换占位frontend/(未指定则使用 base/frontend); - 生成带
wailsVersion: 3元数据的 template.yaml 与NEXTSTEPS.md说明文件。
发布为远程模板后,团队即可一行命令复用脚手架:
wails3 init -n myapp -t https://github.com/yourname/your-template # 默认分支最新提交 wails3 init -n myapp -t https://github.com/yourname/your-template@v1.0.0 # 固定版本标签远程模板属于第三方代码,安装时 Wails 会展示明确警告并要求确认(templates.go),只有用户显式接受责任后才创建项目。
小结
从本文可以梳理出 Wails3 项目的完整生命周期:wails3 init基于_common共享层与框架模板生成骨架 →wails3 dev借助WAILS_VITE_PORT(默认 9245)与 Vite 实现前后端热重载 →wails3 build经 Taskfile 按GOOS分派平台构建并产出build/bin可执行文件。_common模板中的 main.go.tmpl 同时示范了资源嵌入、服务绑定、类型化事件与窗口创建四大核心 API,是你后续开发与自定义模板的可靠起点。建议在实际项目中先跑通wails3 dev热重载闭环,再对照 v3/examples 逐步探索事件、窗口、菜单与系统集成等高级能力。
【免费下载链接】wailsCreate beautiful applications using Go项目地址: https://gitcode.com/gh_mirrors/wa/wails
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考