Zig and WebAssembly in the browser
I'm starting to learn the Zig programming language, and wanted to see how easy it is to load it in the browser with WebAssembly. I noticed that the official documentation only includes a Node.js example, so I thought I'd write up an example for the browser here.
The math.zig
file looks the same as the official example:
extern fn print(i32) void;
export fn add(a: i32, b: i32) void {
print(a + b);
}
Essentially we're exporting the add()
function written in Zig, and using a function called print()
that we have to define in JavaScript.
To compile it, run
zig build-lib math.zig -target wasm32-freestanding -dynamic -rdynamic
The JavaScript file index.js
looks like this:
const imports = {
env: {
print: (result) => {
document.getElementById('text').innerHTML = `The result is ${result}`;
}
}
};
try {
const response = await fetch("math.wasm");
const bytes = await response.arrayBuffer();
const result = await WebAssembly.instantiate(bytes, imports);
const add = result.instance.exports.add;
add(1, 2);
} catch (err) {
console.log(err);
}
In short, we can use the built-in fetch()
to get the math.wasm
file we compiled in the previous step. We then instantiate the WebAssembly code, and we can use the add()
function that we wrote in Zig. The print()
function gets defined as part of the imports
object.
All that's left is to create a simple index.html
:
<!doctype html>
<html>
<head>
<title>Zig in the browser</title>
</head>
<body>
<div id="text"></div>
<script type="module" src="index.js"></script>
</body>
</html>
Take note that we're defining index.js
as a module, so that we can use top-level await
in JavaScript.
The easiest way to start up a simple web server to run the code is
python -m http.server
which you can then access in your browser by going to http://localhost:8000
.
Thoughts? Discuss... if you have a write.as account.