tinygo webassembly 试用
主要是简单测试下tinygo 的使用,同时基于vite 进行web 的集成构建
wasm 生成
注意只测试标注类型支持比较多,其他的就没添加,其他类型的需要自己处理,这点上wasm-pack 处理的比较好
- main.go
package main
//go:wasm-module
//export add
func add(x, y uint32) uint32 {
return x + y + 100
}
//go:wasm-module
//export printName
func printName() int {
return 1111
}
// main is required for the `wasi` target, even if it isn't used.
func main() {}
- 构建
tinygo build -o main.wasm -target=wasi main.go
web 集成
会有wasm 文件的加载,webassembly 实例的初始化,以及方法的导出使用,这点vite 实际上支持支持wasm 文件的初始化
测试中我直接使用了tinygo 官方的示例,实际上可以参考vite 对于webassembly 支持进行调整
- package.json
{
"name": "tinygo",
"version": "1.0.0",
"type": "module",
"main": "index.js",
"license": "MIT",
"scripts": {
"build": "vite build",
"dev": "vite",
"preview": "vite preview"
},
"devDependencies": {
"vite": "^4.5.0"
}
}
- index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World - Go</title>
</head>
<body>
<!--
The wasm_exec.js must come before our Javascript (index.js),
as it defines some global objects
-->
<script type="module" src="./wasm_exec.js"></script> // 此文件是从tinygo 安装中拷贝的,比较重要
<script type="module" src="./index.js"></script>
</body>
</html>
- index.js
实际上就是调用webassembly 初始化工具类的方法
// Imports are from the demo-util folder in the repo
// https://github.com/torch2424/wasm-by-example/blob/master/demo-util/
import { wasmBrowserInstantiate } from "./instantiateWasm.js";
import wasmUrl from './main.wasm?url'
const go = new Go(); // Defined in wasm_exec.js. Don't forget to add this in your index.html.
const runWasmAdd = async () => {
// Get the importObject from the go instance.
const importObject = go.importObject;
// Instantiate our wasm module
const wasmModule = await wasmBrowserInstantiate(wasmUrl, importObject);
// Allow the wasm_exec go instance, bootstrap and execute our wasm module
go.run(wasmModule.instance);
// Call the Add function export from wasm, save the result
const addResult = wasmModule.instance.exports.add(2433, 24);
const printName = wasmModule.instance.exports.printName();
// Set the result onto the body
document.body.textContent = `Hello World! addResult: ${addResult} -- printName: ${printName}`;
};
runWasmAdd();
- instantiateWasm.js 是一个工具类
实际上可以使用vite 的记性呢替代
export const wasmBrowserInstantiate = async (wasmModuleUrl, importObject) => {
let response = undefined;
if (!importObject) {
importObject = {
env: {
abort: () => console.log("Abort!")
}
};
}
if (WebAssembly.instantiateStreaming) {
response = await WebAssembly.instantiateStreaming(
fetch(wasmModuleUrl),
importObject
);
} else {
const fetchAndInstantiateTask = async () => {
const wasmArrayBuffer = await fetch(wasmModuleUrl).then(response =>
response.arrayBuffer()
);
return WebAssembly.instantiate(wasmArrayBuffer, importObject);
};
response = await fetchAndInstantiateTask();
}
return response;
};
- 运行效果
yarn dev
- 构建
yarn build
说明
vite 对于webassembly 的支持还是比较方便的,可以快速的进行项目打包
参考资料
https://tinygo.org/docs/guides/webassembly/wasi/
https://vitejs.dev/guide/features.html#webassembly
https://tinygo.org/docs/guides/webassembly/wasm/