The world’s easiest introduction to WebAssembly🕹

By Martin Olsansky (olso)

An interactive <canvas> laser game for cats 🐈 on your phone 📱written completely in Golang. Being inspected by Matsu 😼
  • Do you think that WebAssembly (WASM) is only used for image manipulation, hard math, or other niche use cases on the web?
  • Are you still confusing WASM with Web Workers and Service Workers?
  • Not interested because you think that JavaScript web apps being developed today will still need to be maintained for the next 10+ years?
  • Do you want to do frontend web development in non-JS languages?

For the skimmers, here are the links to demo or /src 😉. “Reading/writing is a transaction”, I’ll try not to waste your time. There are gists with explanatory comments in the code.

Our goal is to create a simple game for cats 🐈: moving a red laser on mobile with some 🔈 audio effects and vibrations. We will implement everything in Golang (Go), including DOM manipulation, logic, and state.

Aaaaaand since, cats cannot use a mouse, we’ll need touch interaction for those cat paws 🐾.

Think of WASM as the Universal Virtual Machine (sandbox), where you write ANY code once, and it runs everywhere.

WASM is a compile target, not a language. As if you were to compile for Windows, Mac OS, and Linux at once!

I don’t think that WASM is about dethroning JS, it’s about having alternatives without any sacrifices.

Imagine all the people that are developing in Go, Swift, Rust, Ruby, C++, OCaml or others. Now, they can use their preferred language to create an interactive, networked, fast, offline-capable websites and web apps.

Have you ever been part of a discussion about whether your project will be a mono-repo or a multi-repo?

You’re now also going to have a discussion about whether your project is a mono-language or a multi-language.

When people can work with the same tech stack, everything becomes easier. Especially communication between teams.

You can still use React, Vue but now you’re not forced to use JS anymore.

Service & Web Workers allow you to run background, offline & caching processes. They mimic threading, don’t have access to DOM and can’t share the data (only through messaging) and are running in a separate context. Heck, you could even run WASM instead of JS in them. To me, they only provide some abstraction layer with special privileges, nobody said that these layers have to execute JS.

Service & Web Workers are a browser feature, they are not some exclusive JS feature.

We’re going to use WASM, Go, JS and (optionally) Docker 🐳.

If you don’t know Go but know JS, learn Go and then come back here. Let’s start by going to the Go WASM wiki.

Use your local go, I’m using golang:1.12-rc Docker image. Just set two WASM flags for the go compiler here. Create a simple hello world within main.go to test it.

$ GOOS=js GOARCH=wasm go build -o game.wasm main.go

Now, grab the wasm_exec.js glue provided by the Go team. This Go global abstracts WASM initiation. We don’t have to craft any DOM abstraction from scratch 😼. Finally, fetch the .wasm file and run our game.

All in all, it should look like this:

To render our simple game, <canvas> should be sufficient. We can create the DOM structure and elements right from the Go code! That syscall/js (included as a standard Go package) handles the DOM interaction for us.

I bet you haven’t seen main() in a long time 😅.

Looks pretty similar to JS, doesn’t it?

Yes, that’s all you need to interact with the DOM! Just a few Get and Call functions for now.

Oh mama 😻 It’s there!

At this point, I was asking myself. I’m still kind of writing JS in some way… how is this an upgrade? Because we don’t have direct access to the DOM yet, we have to resort to calling the DOM (via JS) in order to do anything. Imagine how you could abstract this away with let’s say, JSX/React. Actually, you already can, but let’s leave that for my next article 😉.

Directly using the syscall/js lib reveals some ES5-like callbacks. We are able to listen for the DOM events. Looks very clean with those static types!

In Go, there is a convention to write all the func in a sync way. It’s up to the caller to decide whether func is async. Making a func run asynchronously is really easy. Just prefix it with go and there you go! It creates a thread with its own context. You can still bind the parent context to it, don’t worry.

That code creates an unbuffered channel, and attempts to receive from it. And since no-one ever sends anything on it, it’s essentially a blocking forever operation, allowing us to run our program forever.

No state management to see here, just a simple typed struct, that doesn’t allow you to pass any incorrect values inside.

The fact that WASM is still considered an MVP (MAP) and that you can create a game like this, without writing a single line of JS, is amazing! CanIUse is already fully green, there is nothing stopping you from building WASM powered websites and apps.

Look, you can combine all the languages you want, event JS -> WASM. In the end, they’ll all compile down to the WASM bytecode. If you need to share anything between them, you can, because they can share a raw memory.

What I’m afraid of is, in recent news, we learned that Microsoft is building a Chromium browser and Firefox market share is below 9%. This gives Google a kill switch power over WASM. If they don’t go with it, masses may never know.

Gameplay 😻

Agreed, my example just draws a full-page canvas . Here are more advanced examples that focus on the semantic web awesome-wasm#web-frameworks-libraries.

Quite a few projects have jumped on the WASM train already. Some of the more interesting to me are Spotify, Twitch, Figma & EWASM.

Nowadays, if you want to use some Ethereum wallet on the mobile web, you have to download a mobile wallet like Status.im from some centralized App Store and trust all the parties.

How about a Progressive Web App that would run geth (Go Ethereum client) with light sync over WebRTC? It could use Service Worker to update its WASM code and run in it the background, could be hosted on IPFS/Dat.

awesome-wasm, awesome-wasm-langs, gowasm-experiments, WasmWeekly, WasmRocks, SPA with C++, better DOM bindings for Go

Thanks to https://github.com/twifkak for optimizing Go on the Chrome for Android!

We will take a look at interoperability with JS modules & React. Stay tuned!

If you liked it and would like to see more content, don’t forget to follow and keep pressing that clap button 😌.