github.com/aykevl/tinygo@v0.5.0/src/examples/wasm/README.md (about) 1 # TinyGo WebAssembly examples 2 3 The examples here show two different ways of using WebAssembly with TinyGo; 4 5 1. Defining and exporting functions via the `//go:export <name>` directive. See 6 [the export folder](./export) for an example of this. 7 1. Defining and executing a `func main()`. This is similar to how the Go 8 standard library implementation works. See [the main folder](./main) for an 9 example of this. 10 11 ## Building 12 13 Build using the `tinygo` compiler: 14 15 ```bash 16 $ tinygo build -o ./wasm.wasm -target wasm ./main/main.go 17 ``` 18 19 This creates a `wasm.wasm` file, which we can load in JavaScript and execute in 20 a browser. 21 22 This examples folder contains two examples that can be built using `make`: 23 24 ```bash 25 $ make export 26 ``` 27 28 ```bash 29 $ make main 30 ``` 31 32 ## Running 33 34 Start the local webserver: 35 36 ```bash 37 $ go run main.go 38 Serving ./html on http://localhost:8080 39 ``` 40 41 `fmt.Println` prints to the browser console. 42 43 ## How it works 44 45 Execution of the contents require a few JS helper functions which are called 46 from WebAssembly. We have defined these in 47 [wasm_exec.js](../../../targets/wasm_exec.js). It is based on 48 `$GOROOT/misc/wasm/wasm_exec.js` from the standard library, but is slightly 49 different. Ensure you are using the same version of `wasm_exec.js` as the 50 version of `tinygo` you are using to compile. 51 52 The general steps required to run the WebAssembly file in the browser includes 53 loading it into JavaScript with `WebAssembly.instantiateStreaming`, or 54 `WebAssembly.instantiate` in some browsers: 55 56 ```js 57 const go = new Go(); // Defined in wasm_exec.js 58 const WASM_URL = 'wasm.wasm'; 59 60 var wasm; 61 62 if ('instantiateStreaming' in WebAssembly) { 63 WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) { 64 wasm = obj.instance; 65 go.run(wasm); 66 }) 67 } else { 68 fetch(WASM_URL).then(resp => 69 resp.arrayBuffer() 70 ).then(bytes => 71 WebAssembly.instantiate(bytes, go.importObject).then(function (obj) { 72 wasm = obj.instance; 73 go.run(wasm); 74 }) 75 ) 76 } 77 ``` 78 79 If you have used explicit exports, you can call them by invoking them under the 80 `wasm.exports` namespace. See the [`export`](./export/wasm.js) directory for an 81 example of this. 82 83 In addition to this piece of JavaScript, it is important that the file is served 84 with the correct `Content-Type` header set. 85 86 ```go 87 package main 88 89 import ( 90 "log" 91 "net/http" 92 "strings" 93 ) 94 95 const dir = "./html" 96 97 func main() { 98 fs := http.FileServer(http.Dir(dir)) 99 log.Print("Serving " + dir + " on http://localhost:8080") 100 http.ListenAndServe(":8080", http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 101 if strings.HasSuffix(req.URL.Path, ".wasm") { 102 resp.Header().Set("content-type", "application/wasm") 103 } 104 105 fs.ServeHTTP(resp, req) 106 })) 107 } 108 ``` 109 110 This simple server serves anything inside the `./html` directory on port `8080`, 111 setting any `*.wasm` files `Content-Type` header appropriately.