欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 高考 > Golang WebAssembly(wasm) 优化 | 减少 wasm 大小

Golang WebAssembly(wasm) 优化 | 减少 wasm 大小

2025/9/15 20:19:11 来源:https://blog.csdn.net/yes169yes123/article/details/143616241  浏览:    关键词:Golang WebAssembly(wasm) 优化 | 减少 wasm 大小

Golang WebAssembly(wasm) 优化 | 减少 wasm 大小

最近项目使用到第三方项目作为 H5 IM 部分的实现,其中前端引入其提供的 SDK,经研究发现 H5 前端 SDK 是基于 Golang 实现的 WASM 用于处理实时消息。
由于 Golang WASM 部分的逻辑复杂,在使用过程中发现 WASM 体积偏大,导致前端加载速度比较慢,因此尝试缩减 WASM 体积。
经过优化,可以将编译后的 WASM 从原本的 31.6MB 优化到 14.56MB,约 53% 的大小,经 Gzip 压缩之后的体积从 6MB 压缩到 3.5MB。

优化步骤

在优化的过程中,我们可以使用 go-weight 查看打包出来的 WASM 中各个包所占用大小。
命令行如下:

GOOS=js GOARCH=wasm goweight

尝试使用 tinygo 直接替换原生编译器。

tinygo 是一款针对微型硬件和 WASM 运行环境的 Go 编译器。
使用 tinygo 编译出的 WASM 体积比原生编译器要小很多,经过尝试验证确实如此。
但编译出来的 WASM 无法直接替换原生编译出的 WASM,经过测试发现,原因是 tinygo 不支持 reflect,甚至任何依赖 reflect 的库都无法运行(可以编译)。
该问题详细可见 Github issues - Tinygo need serialization tools。
那么我们只能选择继续使用 Golang 原生编译器。
如果您的项目并不依赖任何反射或者序列化,可以尝试用 tinygo 进行替换,但需要查看对应的原生库和第三方库兼容性,部分兼容性可以查阅 Packages supported by TinyGo。

对于 tinygo 编译,只需要将 -target wasm 参数添加到编译命令中,例如原编译命令如下:

GOOS=js GOARCH=wasm go build -trimpath -ldflags “-s -w” -o output.wasm main.go

使用 tinygo 替换原生编译器,编译命令如下:

tinygo build -o output.wasm --target wasm main.go

裁剪无用或者冗余代码。

由于我们项目只使用到该 IM 的部分功能,因此我们可以先尝试移除部分无用代码。
经过试验以及测试,发现确实能减少 WASM 打包的体积,因此我们可以确定的一个点:
减少项目使用到的代码是可以减少编译的 WASM 体积。
所以您如果有相同的目标(缩减 WASM 大小),我推荐你尽可能移除无用代码,包括单元测试的代码,哪怕您已经指定了 go:build js && wasm。
因为哪怕无用代码中有依赖到的包,都会影响到最终 WASM 体积。

尽可能移除第三方依赖包或者使用针对 WASM && js 环境的依赖包

既然减少代码可以减少 WASM 体积,因此我们可以尝试移除了第三方依赖包。
在此过程中,我尝试将原本的代码依赖的的库的部分代码直接复制到项目之中,而并非直接引入。
除此之外,我们还可以尝试将部分第三方库进行替换,例如

  • Protobuf 可以使用 protobuf-go-lite 替换,该库提供了 Protobuf 的序列化和反序列化,且编译后占用的体积更小。
  • uber/zap 日志库可以使用 golang 原生的 slog 替换。
  • WebSocket 可以使用 github.com/coder/websocket 替换,该库提供了针对 JS WASM 的 WebSocket 的实现。

使用 wasm-opt 工具缩减体积

在上述过程中,我们已经尝试将原本 Golang 编译出来的 WASM 尽可能缩减体积。
那么接下来,我们可以尝试将已经缩减体积的 WASM 再通过 wasm-opt 工具进行进一步优化。
wasm-opt 是 WebAssembly/binaryen 提供的工具,详细可参考 Binaryen Optimizations。
您可以在 Github Releases 中下载对应的版本,解压后打开 bin 目录就可以找到 wasm-opt 执行文件.
执行 wasm-opt 命令即可实现对 wasm 文件的体积优化。

wasm-opt -Oz --enable-bulk-memory -o ./output.opt.wasm ./input.wasm

基于 CDN 的静态资源加载优化

启用 CDN 的 br 或者 gzip 压缩能够让浏览器加载的时候速度更快,从而进一步优化加载时间。
尤其在使用 WebAssembly.instantiateStreaming() 的场景下,启用压缩能明显优化加载 WASM 的时间,提升用户体验。

参考资料

  • https://go.dev/wiki/WebAssembly
  • https://github.com/tinygo-org/tinygo
  • https://github.com/coder/websocket
  • https://github.com/aperturerobotics/protobuf-go-lite
  • https://github.com/paralin/goweight
  • https://github.com/WebAssembly/binaryen

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com