Best Practices for WebAssembly using GoLang (1.15+)
By: Cesar William Alvarenga
Tags: Gzip, Go, Tinygo, Golang, Webassembly

Best Practices for WebAssembly using GoLang (1.15+)

Photo made with Canva.

In my last post, I showed you how to configure, develop, and generate a WASM file via GoLang. In this post, I will show you the best practices and how to use these strategies in a real modern web project.

Why Reduce the Binary File Size

If you already generate a web assembly binary file using Go, you’ve probably noticed how big the file size is. As we load this binary file on a web page, it will affect the load of other assets on the page. It can affect Time to Interactive (TTI) as well. TTI measures how long it takes a page to become fully interactive. A longer TTI can create a frustrating user experience, such as, the site appears to be ready, but when the user tries to interact with it, nothing happens.

I’ll show you two strategies to generate a smaller binary file size. The first one (recommended for most cases) is using gzip, and the other one is using a compiler called TinyGo.

Using gzip (recommended)

Gzip is a file format and software application used on Unix and Unix-like systems to compress HTTP content before it’s served to a client. We will use the gzip command after compiling our Go file.

We are going to using this Go file (from my last post) as an example:

Compiling Our Go Code

Before we go all-in on the gzip compression, there’s something we can do to make binaries smaller: strip them.

We can use the -s and -w linker flags to strip the debugging information like this:

GOOS=js GOARCH=wasm go build -ldflags="-s -w" -o main.wasm

In this strategy, we will use the same Wasm JavaScript loader that we generated in my last post about WebAssembly:

$ cp “$(go env GOROOT)/misc/wasm/wasm_exec.js” .

Compress the Wasm File

To gzip our compiled file main.wasm , we will use the following command:

gzip -9 -v -c main.wasm > main.wasm.gz

Create the HTML File

In order to use our compressed binary in our HTML document, we must inflate (or ungzip) the gzip-compressed file. To do that, we can use the Pako JS library, and then we will instantiate our Go program as usual. First, we will import the Pako library from a CDN and then use the ungzip function to inflate our file.

Here is a complete example of the HTML file using a Wasm (compiled from the Go file that we created in the last post) compressed by gzip:

Using TinyGo

TinyGo is a Go compiler developed for use in small places. TinyGo does not aim to be able to compile any possible Go program. The compiler compiles most Go programs without modifications. Most language features that are supported, include: slices, interfaces, closures, and bound methods.

TinyGo is a Go compiler intended for use in small places. It reuses libraries used by the Go language tools alongside LLVM to provide an alternative way to compile programs written in the Go programming language.

Install TinyGo

The command above will install the TinyGo on macOS using brew. Here you can find instructions for Linux, macOS, Windows, and Docker.

$ brew tap tinygo-org/tools

$ brew install tinygo

Generate the Wasm JavaScript Loader

In my last post, I showed you how to generate the Wasm JavaScript loader when you are using the default Go compiler. When you are using TinyGo, you have to generate the loader this way:

cp $(tinygo env TINYGOROOT)/targets/wasm_exec.js .

Compiling Your Go Code

tinygo build -o main.wasm -target wasm ./main.go

Now you can load the main.wasm in your HTML as we did in my last post.

Conclusion

In this post, we learned how to reduce the Wasm binary file to improve the page of our application. We saw two strategies that should be chosen according to what features you’re using in your Go program. Next time, I’ll show you how to use a Web Assembly file in a React application via Webpack.