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.