首页 / Wails 入门教程 / 创建第一个应用:wails init

Wails 入门教程

创建第一个应用:wails init

本教程共 42 篇 · 第 5 篇 · 更新于 2026-08-03

Wailswails init项目结构react-ts

5. 创建第一个应用:wails init

本节目标

  • wails init 生成一个 react-ts 模板项目
  • 认得生成目录里每个文件和文件夹的职责
  • 看懂 main.goapp.go 分别放什么
  • 知道 wails.json 和前端目录的关系

5-1 一条命令生成脚手架

环境就绪后,建项目只用一条命令:

wails init -n myapp -t react-ts

-n 指定项目名(也是默认窗口标题和产物名),-t 指定前端模板。本教程主线用 react-ts(React + TypeScript)。Wails 还内置了 vuevue-tssveltesvelte-tspreactpreact-tslitlit-tsvanillavanilla-ts 等模板,但全程以 React 为准。

命令跑完,当前目录多出一个 myapp/ 文件夹,cd 进去:

cd myapp
Tip

第一次 wails init 会比较慢,因为它要拉前端模板并 npm install 装依赖。卡在装包这步别急,网络慢就等一等,或者手动进 frontend/ 目录跑 npm install 也行。

5-2 目录结构逐一看

生成的项目长这样(省略了前端里的 node_modules):

myapp/
├── build/              # 构建输出目录,也放图标等资源
├── frontend/           # 前端工程(React + Vite + TS)
│   ├── src/            # 你的前端代码
│   ├── package.json
│   ├── index.html
│   └── vite.config.ts
├── app.go              # 后端业务逻辑(你主要改这里)
├── main.go             # 程序入口,配置并启动 Wails
├── go.mod              # Go 模块定义
├── go.sum
└── wails.json          # Wails 项目配置

几个关键点对号入座:

main.go 是进程的入口,里面调用 wails.Run(&options.App{...}) 启动应用。窗口尺寸、标题、要绑定的结构体、生命周期钩子,都在这个 options.App 里配置。第 8 章会专门拆每个字段。

app.go 放你的业务代码。模板默认定义了一个 App 结构体,带一个 startup(ctx) 方法(存 context)和一个示例 Greet(name) 方法。你后面要暴露给前端的方法都写在这里,或写在其他结构体里再挂进 Bind

frontend/ 就是个标准前端工程。Wails 不干涉你用 Vite、React 的那套写法,npm run devnpm run build 照常工作。区别是 wails dev / wails build 会接管前端的构建,并额外生成 wailsjs 绑定目录。

build/ 平时是空的,构建时 Wails 把产物(exe / app)和图标放这里。你也可以预先放一份应用图标,构建时会用上。

wails.json 是 Wails 自己的项目配置,管前端目录在哪、构建输出叫什么、dev 时监听哪些目录等。第 7 章逐字段讲。

5-3 main.go 里有什么

打开 main.go,核心就这几行(模板略有出入,结构一致):

package main

import (
	"embed"
	"log"

	"github.com/wailsapp/wails/v2"
	"github.com/wailsapp/wails/v2/pkg/options"
	"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)

//go:embed all:frontend/dist
var assets embed.FS

func main() {
	app := NewApp()
	err := wails.Run(&options.App{
		Title:      "myapp",
		Width:      1024,
		Height:     768,
		AssetServer: &assetserver.Options{
			Assets: assets,
		},
		OnStartup: app.startup,
		Bind:      []interface{}{app},
	})
	if err != nil {
		log.Fatal(err)
	}
}

//go:embed all:frontend/dist 把前端打包产物编进二进制——这就是单文件分发的来源。Bind 里放 appapp.go 里的公开方法才能被前端调用。模板已经帮你接好了,省去手动接线。

5-4 app.go 里有什么

app.go 是你要天天改的文件:

package main

import (
	"context"
	"fmt"
)

type App struct {
	ctx context.Context
}

func NewApp() *App {
	return &App{}
}

func (a *App) startup(ctx context.Context) {
	a.ctx = ctx
}

func (a *App) Greet(name string) string {
	return fmt.Sprintf("Hello %s, It's show time!", name)
}

Greet 首字母大写,是公开方法,会被绑定到前端。startup 是小写的私有方法,同时被挂进 OnStartup 生命周期回调,Wails 不会把它当业务方法暴露出去。后面你加新方法,照着 Greet 的样子写、保证首字母大写即可。

5-5 现在能跑起来了吗

生成完先别急着改,确认脚手架是好的:

wails dev

能弹出一个窗口、里面显示模板界面,说明 init 成功、环境也没问题。wails dev 的细节第 6 章讲,现在只要确认”窗口能开、界面能看”就够了。

Warning

如果 wails dev 报前端构建错误,先看是不是 frontend/ 里依赖没装全(网络中断常导致 npm install 半途而废)。进 frontend/ 手动 npm install 再重试,比直接怀疑 Wails 更准。

5-6 模板选型与依赖补全

wails init-t 还能选 vuevue-tssveltesvelte-tspreactpreact-tslitlit-tsvanillavanilla-tsvanilla 就是不带框架的原生 HTML/JS 模板)。团队是 Vue 栈就选 vue-ts,Wails 对前端框架没有偏爱。但本教程统一 React + TypeScript,原因有二:其一 React 生态最大、资料最多;其二 TypeScript 能和 Wails 生成的 .d.ts 类型声明天然配合,调 Go 方法时有类型提示和编译期检查,少踩很多坑。

另一个容易忽略的点:wails init 会顺带执行 npm install 把前端依赖一次装好。若当时网络不好装到一半失败,后面 wails dev 会在前端构建这步报错。遇到这种情况不必重新 init,直接进 frontend/ 目录手动 npm install 补齐依赖即可,脚手架不会丢。

顺带看一眼 frontend/package.json 里的脚本:dev 起 Vite 开发服务器、build 打生产包、preview 本地预览。这些脚本 Wails 在 dev/build 时就是按 wails.json 里的 frontend:dev:watcherfrontend:build 调用它们的,你改了脚本名也要同步改 wails.json。

5-7 模板界面其实在演示什么

第一次 wails dev 起来,窗口里默认是一个输入框加按钮的欢迎界面。它不只是一段装饰,而是在现场演示绑定通路:你在输入框打字、点按钮,前端就把文字传给 Go 的 Greet 方法,Go 拼好问候语返回,前端再显示出来。看懂这个来回,你就看懂了 Wails 的核心玩法。

之后你写的任何功能都是同一套:前端收集输入、调绑定的 Go 方法、拿返回值更新界面。模板的价值正是用最小代价把这个闭环跑通给你看,所以别急着把界面删光,先确认它能正常响应再动手改。很多人一上来就清空 src 重写,结果连”绑定到底通没通”都没验证,后面出问题更难定位。

5-8 目录结构记不住就常回看

刚上手记不住每个文件干嘛很正常。把 app.gomain.gofrontendwails.json 这四块的关系贴在便签上,写代码时对照,几天就熟了。理解结构比背命令重要,结构通了,后面每章的配置你都知道该往哪放、出了问题该去哪查。

常见误区

以为 wails init 只生成 Go 代码。它同时拉了一份完整前端工程并装依赖。前端目录结构和普通 Vite 项目没两样,你已有的前端经验直接能用。

把业务逻辑全堆在 main.go。保持模板的分层:main.go 只做启动配置,app.go(或你新建的结构体)放业务。混在一起后面难维护。

改了 Go 方法名却忘了前端 import 路径wailsjs 是生成的,方法名一变,前端那行 import { Greet } from "../wailsjs/go/main/App" 就要跟着改。IDE 报红线时第一反应是去核对生成文件。

小结

wails init -n 名 -t react-ts 一次性生成 Go 入口(main.go)、业务文件(app.go)、前端工程(frontend/,标准 Vite + React)、构建目录(build/)和 Wails 配置(wails.json)。main.go 负责启动和配置,app.go 放你要暴露的方法,frontend/ 是你的界面老家。脚手架生成后跑一次 wails dev 验证窗口能开,下一章就正式讲开发模式和构建。