前端集成:Wails 如何驱动前端
本教程共 42 篇 · 第 9 篇 · 更新于 2026-08-03
9. 前端集成:Wails 如何驱动前端
本节目标
- 知道 Wails 往 index.html 里注入了哪两个关键脚本
- 理解 Vite 在开发模式里是怎么被接上的
- 在 React 里用
wailsjs绑定和window.runtime跟 Go 通信 - 知道什么场景要关掉自动注入、怎么关
9-1 前端是怎么被加载的
Wails 不自己造前端框架,它做的是把你的前端工程”塞”进桌面窗口。背后的流程是:
- 构建/运行时,AssetServer 从
embed.FS(生产)或 Vite 服务器(开发)拿出index.html。 - Wails 在把页面交给 WebView 之前,自动往
<head>里注入两个脚本:/wails/ipc.js和/wails/runtime.js。 - WebView 加载这个被处理过的
index.html,你的 React 应用照常启动。
这两个脚本干的事完全不同:
/wails/ipc.js 是桥的 JS 端。前端调用绑定方法时,实际是它把请求序列化、交给原生桥送到 Go,再把返回值送回来。你写的 import { Greet } from "../wailsjs/go/main/App" 底层就走它。
/wails/runtime.js 是运行时 API 的 JS 端。它把 window.runtime 这个全局对象挂上,前端用它调事件、对话框、窗口控制等(Go 侧的 runtime 包对应前端就是它)。第 14 章起的运行时各章都会用到。
Note这两个脚本是 Wails 自动注入的,你不用手动在
index.html里加<script src="/wails/ipc.js">。加了反而可能重复加载。只要用官方模板,它们就在那。
9-2 Vite 在开发模式怎么接
react-ts 模板用的是 Vite。wails dev 时,Wails 会启动 Vite 开发服务器(执行 frontend:dev:watcher,默认 npm run dev),前端资源从 http://localhost:5173 这类地址来。Wails 自己起一个内部服务,把 WebView 的请求导向 Vite,并照常注入那两个脚本。于是你改前端代码,Vite 热重载,窗口里立刻能看到。
生产模式(wails build)下没有 Vite:前端先 npm run build 成静态文件,被 //go:embed 编进二进制,AssetServer 直接从 embed.FS 读。两个脚本依然会被注入,只是来源从”服务器”变成”二进制里的资源”。
这就是为什么同一套前端代码,dev 能热重载、build 是死的——加载来源变了,注入动作没变。
9-3 React 主线怎么跟 Go 说话
模板里的 React 工程结构和普通 Vite + React 项目没区别。你主要跟两样东西打交道:生成的绑定、全局运行时。
调用绑定的 Go 方法,直接 import 生成文件,当异步函数用:
import { useState } from "react";
import { Greet } from "../wailsjs/go/main/App";
export default function App() {
const [msg, setMsg] = useState("");
const onClick = async () => {
const result = await Greet("码上学");
setMsg(result);
};
return (
<div>
<button onClick={onClick}>打招呼</button>
<p>{msg}</p>
</div>
);
}
../wailsjs/go/main/App 这条路径:相对你的组件位置走,main 对应 Go 的 package main,App 对应绑定的结构体名。
调用运行时 API,走全局对象 window.runtime:
// 发一个事件给 Go(Go 用 runtime.EventsOn 接收)
window.runtime.EventsEmit("frontend-ready", { time: Date.now() });
// 打开外部浏览器
window.runtime.BrowserOpenURL("https://wails.io");
window.runtime 上的方法名和 Go 侧 runtime 包一一对应,只是换成 JS 风格(首字母大写、带命名空间)。
Tip调试时不用翻代码,直接在
wails dev -browser打开的页面控制台敲window.go.main.App看绑定的方法,敲window.runtime看运行时 API。这两个全局对象就是前端和 Go 之间的全部入口。
9-4 什么情况要关闭自动注入
绝大多数项目用默认注入就好。但有一类场景要关掉:用自带 dev server 的前端框架(比如 Create React App,不是 Vite)。这类框架自己起服务器,Wails 通过 frontend:dev:serverUrl 连过去,但默认的自动注入会和框架自身的脚本处理打架。
关法是给 index.html 的 <head> 加一个 meta:
<meta name="wails-options" content="noautoinject">
加了之后,Wails 不再自动注入那两个脚本,你需要按框架的方式手动引入(官方文档给了对应该框架的写法)。react-ts 模板用的是 Vite,不需要这步,别画蛇添足。
Warning只有”用非 Vite 的外部 dev server”才需要
noautoinject。Vite 模板下你手动加了这个 meta,会导致window.runtime和绑定都加载不出来,界面白屏、调 Go 报 undefined。拿不准就别动它。
9-5 前端工程你完全可以自由发挥
Wails 对前端几乎零约束:路由怎么写、状态管理用 Redux 还是 Zustand、UI 库用 Ant Design 还是 MUI,都随你。它只关心两件事——index.html 能被 AssetServer 找到、绑定的方法能被注入的桥访问到。
所以你已有的 React 经验 100% 能用。把 Wails 想成”一个特殊的浏览器容器 + 一组额外的全局 API”,而不是一套新的前端框架,心态就对了。
9-6 window.runtime 常用方法一览
window.runtime 是前端调运行时能力的统一入口,下面这些最常用:EventsEmit / EventsOn / EventsOff 收发事件;Log / LogDebug / LogError 把前端日志打到 Go 侧;BrowserOpenURL 用系统浏览器打开外链;Quit 退出应用;WindowSetTitle / WindowShow / WindowHide 控制窗口显隐。
它们和 Go 侧 runtime 包的方法一一对应,只是名字换成 JS 风格。一个常见疑问是”这些方法哪来的”——答案就是 9-1 说的 /wails/runtime.js 注入脚本,它在页面加载早期就把 window.runtime 挂好了,所以你在 React 组件里随时能用,不必 import。调试时在 wails dev -browser 的控制台直接敲 window.runtime.Log("hello"),能立刻看到调用生效,是验证桥是否通的快捷方式。
9-7 调试技巧收个尾
排前端问题时记住一个万能动作:开 wails dev -browser,在浏览器里用你熟悉的工具看元素、看网络、打断点。浏览器里能跑通,再回桌面窗口确认 WebView 表现,两步就能隔离九成问题。别在黑盒里瞎猜,工具就在手边。
还有一个习惯值得养成:每次新增一个绑定方法,先在控制台敲 window.go.main.App.方法名() 验证它能返回,再写进组件。把”验证绑定”和”写界面”拆成两步,出问题一眼就能分清是 Go 侧没暴露还是前端调用写错。
常见误区
手动往 index.html 加 /wails/ipc.js 的 script 标签。Wails 会自动注入,手动加会重复,可能引出版本错乱。除非你关了自动注入并自己引,否则别加。
以为 React 代码要改造成 Wails 专属写法。不需要。组件、hooks、构建配置都照常,唯一多出来的就是 import wailsjs 和用 window.runtime。
在组件顶层直接 await Greet(...)。绑定方法返回 Promise,调用必须在 async 函数或 useEffect 里。忘了 await 拿到的是 Promise 对象不是结果。
dev 里好用就以为生产也一样。生产资源来自二进制,少了 Vite 热重载和 source map,个别前端行为可能不同,发布前务必 wails build 实测一遍。
小结
Wails 把前端”塞”进窗口:加载 index.html 时自动注入 /wails/ipc.js(桥)和 /wails/runtime.js(运行时),dev 从 Vite 服务器取资源、build 从 embed 取,注入动作不变。React 主线通过 import wailsjs 调绑定的 Go 方法、通过 window.runtime 调运行时 API。默认的 Vite 模板不用管注入;只有用自带 dev server 的非 Vite 框架才需要 noautoinject。Wails 对前端零约束,你现有的 React 能力直接复用。下一章讲前端路由在桌面端怎么摆。