Hopefully simple WebAssembly starting guide

Today we’d be writing our first WebAssembly module to solve the widely known Conway’s Game of Life.

Hopefully simple WebAssembly starting guide

Today we’d be writing our first WebAssembly module to solve the widely known Conway’s Game of Life.

This article is part of a workshop we run at the WebAssembly London Meetup.

This guide is aimed towards web developers, who are already familiarised with the JavaScript ecosystem: NPM, Node, TypeScript, browsers. However, I hope to make it simple and fun for everybody to learn some AssemblyScript (TypeScript to WebAssembly compiler).

What is WebAssembly?

In a nutshell, WebAssembly is a compile target for the web. It is a very simple low-level language that can run in the browser. For example, you could compile C code to WebAssembly and run a C program in the browser. Awesome, right!?

Why WebAssembly?

Web applications are increasingly complex and a better compile target than JavaScript was due for quite some time. We all want to deliver highly optimized web applications like games, complex UIs, etc.

It is possible to write memory and computationally optimized Software using WebAssembly. If your web application has a critical CPU-intensive task, it is very likely that WebAssembly could help you deliver a better experience than JavaScript.

Getting started… Now!

In order to grasp the feeling of building a WebAssembly module, I recommend starting with a simple online IDE. During this guide, we will use WebAssembly.Studio.

Open the https://webassembly.studio page and create a new TypeScript project.

Building your first module

Now that you have a project, simply click “Build and Run” and contemplate the beauty of your WebAssembly browser VM calculating the Answer to the Ultimate Question of Life, the Universe, and Everything.

At the bottom right corner, you will see the answer printed on the screen, for you… and just for you...

Voila! You compiled your first WebAssembly module.

Conway’s Game of Life

Now, we are going to step up and build a more complex piece of Software. It is based upon an official example.

I will guide you along the way explaining what is what, although bear in mind that all the tools used in this tutorial are kind of experimental yet. Therefore, you could encounter some issues along the way.

Demo of the Conway’s Game of Life we are building


Firstly, we need to set up the index.html file adding a canvas tag and very simple styles, so the canvas takes the entire page width and height.

The JavaScript glue code

The WebAssembly module is not something we can run directly from the HTML like JavaScript (using <script> ). We need to instantiate the module using JavaScript:

  • Let the module know how much memory we’d like to allocate for it.
  • Map the input/outputs.
  • Orchestrate the module execution.

Therefore, JavaScript is the master and should have the logic to use the module.

Compiling TypeScript to WASM

We will use the AssemblyScript compiler to compile the project. AssemblyScript comes with the CLI tool ast .

WebAssembly Studio uses Gulp to build the project, so we will stick to that as it is the recommended way to implement the build pipeline.

Note that we need to include the flag --importMemory as we want to have access to the WebAssembly.Memory object within the JS orchestrator.

Now we have all the pieces to write the actual Conway’s Game of Life code.

The actual code

Let’s write some AssemblyScript! AssemblyScript is a subset of TypeScript, with direct mappings to WebAssembly types and a nice standard library mapping to JavaScript APIs. However amazing this tool is, take into account that that AssemblyScript has some limitations.

For this example, we will use the following types and built-ins:

  • i32 : 32-bit integer. Simple, right?
  • u8 : Unsigned 8-bit integer
  • usize : If targetting 32-bit WebAssembly (we are), then it is a u32.
  • load<Type>(pointer: usize): Loads a value of the specified type from memory. Equivalent to dereferencing a pointer in other languages.
  • store<Type>(pointer: usize): Stores a value of the specified type to memory. Equivalent to dereferencing a pointer in other languages when assigning a value.

In the official Wiki, you can find a complete list of types and a complete list of built-ins.

Now the code:


Build and run

Hopefully, you followed along and properly copied and pasted. Now, if you click the button “Build and Run”, you should see the following:

If it didn’t work, you fork this webassembly.studio, let me know in the comments, check out my finished repository, or… even better… debug the problem yourself, which is the best way to learn!

Running locally

We could download the code written in WebAssembly Studio, and it should be fairly easy to get it running:


npm install 
npm i -D serve
npm run build

echo "Conway's Game of Life at http://localhost:5000/src/main" \
  && npx serve

That should build the .wasm file and serve it using a static files server. If it doesn’t work, you could clone my repository, which should work (fingers crossed).

Production use

WebAssembly is widely supported (85% globally at the time of writing).

AssemblyScript surprised me positively because it produces a very small module (about ~450 Bytes!) for our Conway’s Game of Life.

For comparison, I tried to build something similar using Golang 1.11, which has native support to compile to WebAssembly and the produced module size was about ~1.5 MB. It could have definitely been optimized opting out of some Golang features, but that bundle size as it is made the module quite unusable.

Anyhow, the tooling around WebAssembly is maturing very quickly, so we can expect very nice tools in the following months/years.

Final note

WebAssembly is not built to suit every use case, and I believe JavaScript is sufficient for most tasks. However, it can be very useful if a piece of Software has to be highly optimized or relies on preexisting code written in a language that could be compiled to WebAssembly (any language with an LLVM front end).

Regardless, WebAssembly and AssemblyScript are totally valid tools in the developer toolbelt and should be considered when the time comes.