2022年最新将Go打包成wasm体验

3,782 阅读1分钟

网上看了很多将go打包成wasm,但是很多都讲得不是很清楚,不知道是不是东抄抄西抄抄的,步骤缺这儿缺那儿。我找了很多答案之后,才找到将go打包成wasm的方法。

文章参考:juejin.cn/post/713361…

这个作者讲的是最好的,代码都能跑起来,但是作者也是有些没讲到的,我在此作补充。

第一步,初始化go mod,然后编写go程序,这里直接复制原作者的代码

// main.go

package main

import "syscall/js"

func main() {
	message := "👋 Hello World 🌍"

	document := js.Global().Get("document")
	h2 := document.Call("createElement", "h2")
	h2.Set("innerHTML", message)
	document.Get("body").Call("appendChild", h2)
	alert := js.Global().Get("alert")
	alert.Invoke(123)
	<-make(chan bool)
}

但是会遇到这个问题: could not import syscall/js (no required module provides package "syscall/js")

image.png 查了很久,才发现是要配置vscode。在根目录新建.vscode/settings.json,然后配置:

// .vscode/settings.json

{
    "go.toolsEnvVars": {
        "GOARCH": "wasm",
        "GOOS": "js"
    },
    "go.testEnvVars": {
        "GOARCH": "wasm",
        "GOOS": "js"
    },
    "go.installDependenciesWhenBuilding": false
}

这样基本就可以打包wasm了,输入:

set GOOS=js
set GOARCH=wasm
go build -o main.wasm

但是执行后又会出现:imports syscall/js: build constraints exclude all Go files in C:\Program Files\Go\src\syscall\js

image.png 那是因为在powershell中执行,此时又切换回cmd,因为set是临时设置,只在当前窗口有效,所以切换回cmd又要设置一遍:

set GOOS=js
set GOARCH=wasm
go build -o main.wasm

image.png

然后就成功了,接着需要创建html,引入wasm_exec.js,加载wasm。这里网上都有提到需要wasm_exec.js,但就是没有说要怎么获取,幸好原作者提到了怎么得到wasm_exec.js文件,在powershell(不要cmd)执行cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .,就能把wasm_exec.js文件拷贝到根目录中。

image.png

<!-- index.html -->

<html>
    <head>
        <meta charset="utf-8" />
        <script src="wasm_exec.js"></script>
    </head>
    <body>
        <h1>WASM</h1>
        <script>
            // 异步加载wasm文件
            function loadWasm(path) {
                const go = new Go()
                return new Promise((resolve, reject) => {
                    WebAssembly.instantiateStreaming(fetch(path), go.importObject)
                        .then((result) => {
                            go.run(result.instance)
                            resolve(result.instance)
                        })
                        .catch((error) => {
                            reject(error)
                        })
                })
            }
            //加载wasm文件
            loadWasm('main.wasm')
                .then((wasm) => {
                    console.log('wasm已加载 👋')
                })
                .catch((error) => {
                    console.log('加载出错了', error)
                })
        </script>
    </body>
</html>

然后全局安装serve,用服务器跑当前的html

npm i -g serve
serve

访问http://localhost:3000,就能看到wasm的代码了

image.png