MyGo浏览器运行指南:WebAssembly+WebGL2让原生UI跑进网页

原创2026-10-12 18:12:02869 阅读
文章标签:桌面应用跨平台UI组件

MyGo浏览器运行指南:WebAssembly+WebGL2让原生UI跑进网页

MyGo 是一个用 Go 语言开发桌面应用的开源框架,支持 Web 前端与纯 Go 绘制的原生 UI 两种界面。它最有意思的一点是:用纯 Go 写成的原生 UI 应用,代码几乎不用改动,就能编译成 WebAssembly 跑进浏览器,并由 WebGL 2 实时渲染出完整的界面。这篇指南面向新手,讲清楚它背后的原理、两条命令的上手步骤,以及浏览器里哪些能力可用、哪些暂不可用。

一、原生 UI 为什么能跑进浏览器?

传统印象里,"桌面应用"意味着要安装、要打包、要依赖系统组件。而 MyGo 的浏览器模式让同一份 Go 代码直接在网页标签页里运行,原理可以拆成两部分:

1. Go 代码编译为 WebAssembly

mygo 命令行工具会把你的应用以 GOOS=js GOARCH=wasm 编译成 .wasm 文件,再配合 Go 官方的 wasm_exec.js 加载器在页面中启动。也就是说,浏览器里跑的是你的 Go 代码本身,而不是某个 Web 模拟层。相关实现位于 cmd/mygo/web.go。

2. WebGL 2 负责全部画面

原生 UI 的窗口在页面上是一个 <canvas>,由 WebGL 2 绘制——与 Linux 桌面版使用同一个渲染器、同一套着色器。具体细节见 internal/gpu/gl/ 与 internal/web/ 两个模块,docs/architecture.md 的 "Browsers" 一节有更完整的架构说明:

  • 绘制:按设备像素比(device pixel ratio)用 WebGL 2 逐帧渲染,只有内容有变化时才绘制,Liquid Glass 等特效与桌面版表现一致;浏览器若不支持 WebGL 2,会自动退回内存绘制 + 2D canvas 的降级方案
  • 文本:直接借用浏览器自己的字体系统——找字体、缺字回退、换行与双向排版(bidi)都与普通网页一致,system-ui 就是系统字体
  • 输入:鼠标点击计数、滚轮与触控板、键盘、输入法(IME)组合输入、浏览器剪贴板的复制/剪切/粘贴均可用
  • 帧循环:通过 requestAnimationFrame 驱动,页面被隐藏时自动暂停,切回标签页时恢复

💡 对新手来说一句话总结:画面走 WebGL 2,文字走浏览器字体,逻辑就是你原来的 Go 代码。

二、两条命令快速上手:浏览器开发流程

开发模式:mygo dev -web

在一个原生 UI 项目(mygo init -template native 创建的)里执行:

mygo dev -web

它会自动完成四件事:

  1. 把应用编译成 WebAssembly,在 http://localhost:5174 提供页面并打开浏览器
  2. 监听 Go 代码变化,自动重新编译并刷新页面(构建失败时页面保留上一个可用版本,并在其上显示报错原因)
  3. 提供一组快捷键:按 r 重新构建、o 重新打开页面、q 退出
  4. 默认端口被占用时自动尝试下一个可用端口(可用 -port 指定,-open=false 可关闭自动打开)

开发模式的完整实现见 cmd/mygo/web.go,CLI 参数说明见 docs/cli.md。

生产构建:mygo build -platform web

mygo build -platform web

产出物是一个纯静态站点(默认位于 <out>/web 目录),包含:

文件 说明
index.html 加载页面,带加载中的转圈动画
wasm_exec.js Go 官方 WebAssembly 加载器(与编译器版本严格匹配)
<名称>.<内容哈希>.wasm 应用本体,文件名带内容摘要,方便浏览器长期缓存
icon 配置了图标时的应用图标

因为是静态文件,它可以放到任何静态服务器、对象存储或 CDN 上,无需后端。构建逻辑见 cmd/mygo/web.go,浏览器行为的官方文档是 docs/ui/browsers.md。

不走 CLI:纯 Go 方式

不想依赖 mygo 命令时,两条 Go 标准命令也能完成:

GOOS=js GOARCH=wasm go build -o app.wasm .
cp "$(go env GOROOT)/lib/wasm/wasm_exec.js" .

然后写一个最小的 HTML,用 WebAssembly.instantiateStreaming 加载 app.wasm 即可,完整页面模板参考 docs/ui/browsers.md。注意务必通过 HTTP 提供服务(WASM 需要 application/wasm 内容类型),直接用 file:// 打开会失败。

三、浏览器里哪些能力可用?

以仓库里的计数器示例 examples/counter-native/main.go 为例——它的全部界面就是一段 Go 代码(ui.Column + ui.Button + ui.Textf),在桌面和浏览器中运行同一份源码。各能力的支持情况如下:

✅ 浏览器中可用的能力

能力 浏览器中的表现
绘制与特效 WebGL 2 实时渲染,玻璃拟态等特效与桌面一致
文本渲染 使用浏览器字体,支持缺字回退与双向排版
指针 / 键盘 点击、滚轮、触控板、按键均正常
输入法 在光标处正常组合输入
路由 浏览器的前进/后退按钮可走应用内的页面(URL 片段如 #/notes/42),刷新或外链直达也能正确恢复位置
文件拖放 拖文件进窗口可用;浏览器拿不到本地路径,框架会在内部保留最近 16 次拖放的文件,os.ReadFile 等标准库调用照常工作
右键菜单 以 HTML 菜单形式显示在页面上
暗色模式 跟随浏览器的"减少动态""增强对比"等设置,也可在根元素上手动指定
弹窗 Dialog.Message 使用浏览器的 alert / confirm
打开链接 Shell.OpenExternal 会打开新标签页

⚠️ 浏览器中暂不可用的能力

网页窗口、应用菜单与 Dock 菜单、系统托盘、通知、全局快捷键、文件选择对话框、非文件类的数据拖放,以及辅助功能(读屏器等)在浏览器中没有对应的宿主能力,框架会明确报告"不支持"而不是静默失败。

📌 选型建议:如果你的核心界面是"内容型"的(编辑、浏览、可视化),浏览器模式基本无感;如果重度依赖托盘、通知、全局快捷键,则更适合打包成桌面应用。

四、构建产物有多大?

WebAssembly 体积是很多人关心的问题,官方给出的参考数据:

  • 计数器示例:8.2 MB(gzip 压缩后 2.2 MB)
  • 包含全部组件的文档演示应用:9.8 MB(gzip 后 2.6 MB)

体积可控的关键在于:面向浏览器的构建会自动剔除只服务于网页前端的模块(IPC、自定义协议、TypeScript 客户端生成器、自动更新及其加解密代码等),且为浏览器新增的代码不会反向加进桌面构建里。生产构建还会通过 mygo_noinspector 标签再省掉约 350 KB 的内置检查器。

五、把应用嵌入自己的网页

mygo build -platform web 生成的页面默认让窗口铺满整个页面。如果你想把它嵌进已有网站:

  1. 在页面中放一个 ID 为 mygo 的元素,窗口会填满该元素;找不到该元素则填满整个页面
  2. 窗口的大小完全由页面控制(Go 端设置的宽高、位置、标题栏选项在浏览器中不生效),可以用 CSS 布局把它放进任意位置
  3. 后打开的窗口会覆盖先前的窗口,最后打开窗口对应的标题会作为页面标题

六、相关资料与源码索引

七、写在最后

MyGo 的浏览器模式本质上做了一次"桌面到网页的无缝迁移":Go 逻辑编译为 WebAssembly,画面交给 WebGL 2,文字和输入复用浏览器的成熟能力。两条命令(mygo dev -web 开发、mygo build -platform web 发布)即可完成从桌面应用到静态网页站点的切换,产物体积小、部署简单,非常适合让已有的原生 UI 应用获得一个"免安装"的 Web 版本。

登录后查看全文
mygo