# Introduction to WebAssembly with Go


## WebAssembly Overview
What is actually WebAssembly? Here is a snippet from [webassembly.org][1] official website.
> *"WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications."*

OK that sounds mouthful, basically WebAssembly is open standard technology that allows application to be written in high level language such as Go, Rust, and C++ and then compiled into portable binary code and execute it in web browser.

Unlike Javascript, we can ship application within one single `*.wasm` binary file. This means distribution of the application will be faster over the network and broswer can cache the binary.

### Use Cases
There still not a lot of use cases to use WebAssembly, but a notable example is when application require operations with 64-bit integers data type. WebAssembly can overcome limited support for 64-bit integers in Javascript as Javascript doesn't have native 64-bit integers, it only support [53-bit integers][3]. Meanwhile, Go have native 64-bit integers support.

> *Maximum value for an integer with 64-bit is **18,446,744,073,709,551,615** according to [Wolfram Alpha][6]*

WebAssembly can be used to build performant web application that requires heavy workload beyond Javascript capabilities. Figma uses WebAssembly and [achieve 3x faster load][2] albeit it's built with C++ not Go.

### Browser Compatibility
Top 4 (Chrome, Firefox, Edge and Safari) browser have perfect compatibility for WebAssembly, while Internet Explorer doesn't support WebAssembly at all. Opera somewhat compatible with WebAssemly but not fully. Here is the detail on [Browser Compatibility][7] according to Mozilla.

## Go Support for WebAssembly
Go 1.11 added an experimental port to WebAssembly. Go 1.12 has improved some parts of it, with further improvements starting in Go 1.13.

### Compiling to *.wasm
Application written with Go can be compiled to WebAssembly by specifying `GOOS=js` and `GOARCH=wasm` environment variable. Let write some simple Go code.
Prepare a workspace with following structure:
```bash
introduction-to-web-assembly-with-go
├── go.mod
├── public
├── server.go
└── wasm
    └── main.go
```
Add content to `main.go`
```go
package main

import "fmt"

func main() {
	fmt.Println("Hello, Go WebAssembly")
}
```

And then compile it to WebAssembly
```bash
$ GOOS=js GOARCH=wasm go build -o ./public/app.wasm ./wasm/main.go
```

### Javascript Support File
Official documentation for [WebAssembly in Go][9] mention we need to add Javascript support file to load the WebAssembly binary onto the web page. This Javascript file can be copied from `GOROOT` if you already install Go.
```bash
$ cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" ./public/
```

### HTML Boilerplate
Add simple HTML boilerplate to tie up everything together.
```html
<html>
<head>
    <meta charset="utf-8" />
    <script src="wasm_exec.js"></script>
    <script>
        const go = new Go();
        WebAssembly.instantiateStreaming(fetch("app.wasm"), go.importObject).then(
            (result) => {
                go.run(result.instance);
            }
        );
    </script>
</head>
<body></body>
</html>
```

Create simple static HTTP server on `server.go`
```go
package main

import (
	"fmt"
	"net/http"
)

func main() {
	err := http.ListenAndServe(":9090", http.FileServer(http.Dir("public/")))
	if err != nil {
		fmt.Println("Failed to start server", err)
		return
	}
}
```

Run `go run server.go` and point your browser to `localhost:9090` and open browser console, you should see `"Hello, Go WebAssembly"` printed.

### Example Code
Simple WebAssembly code can be found in this [GitHub repository][8]. The file structure should be as follow:
```bash
introduction-to-web-assembly-with-go
├── go.mod
├── public
│   ├── app.wasm
│   ├── index.html
│   └── wasm_exec.js
├── server.go
└── wasm
    └── main.go
```

### Limitations
While WebAssembly is awesome, but there are some limitations. For example, due to browser strict security policy we cannot write application that interact with the filesystem. I would not go into this too deep, it might worth another post.

## Closing
WebAssembly provide versatile solution to offload heavy computation on web pages. This could be applied to games, mathematical calculator, data processing, or even video editor on the web. In my opinion more website will be using WebAssembly in the future. WebAssembly will not replace Javascript for the near future as the ability to interact with DOM still hard to write. Next, I will write on how to interact with WebAssembly from Javascript. Stay tuned!

[1]: https://webassembly.org/
[2]: https://www.figma.com/blog/webassembly-cut-figmas-load-time-by-3x/
[3]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Numbers_and_dates#numbers
[4]: https://go.dev/play/p/kqRlsqyk0FV
[5]: https://go.dev/ref/spec#Numeric_types
[6]: https://www.wolframalpha.com/input?i=2%5E64-1
[7]: https://developer.mozilla.org/en-US/docs/WebAssembly#browser_compatibility
[8]: https://github.com/hyknerf/introduction-to-web-assembly-with-go/tree/v0.1.0
[9]: https://github.com/golang/go/wiki/WebAssembly#getting-started
