Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 1 | WebAssembly |
| 2 | =========== |
| 3 | :toc: |
| 4 | :toc-title: |
| 5 | :toclevels: 2 |
| 6 | :icons: |
| 7 | |
| 8 | |
| 9 | # Introduction |
| 10 | |
Justin Clift | ff596d5 | 2019-04-03 17:41:23 +1100 | [diff] [blame] | 11 | Go 1.11 added an experimental port to WebAssembly. Go 1.12 has |
| 12 | improved some parts of it, with further improvements expected in Go |
| 13 | 1.13. |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 14 | |
| 15 | WebAssembly is described on its https://webassembly.org[home page] as: |
| 16 | |
| 17 | > WebAssembly (abbreviated _Wasm_) is a binary instruction format for |
| 18 | > a stack-based virtual machine. Wasm is designed as a portable |
| 19 | > target for compilation of high-level languages like C/C++/Rust, |
| 20 | > enabling deployment on the web for client and server applications. |
| 21 | |
| 22 | ********************************************************************** |
Justin Clift | b6a26e4 | 2019-05-18 12:32:39 +1000 | [diff] [blame] | 23 | If you're new to WebAssembly read the https://github.com/golang/go/wiki/WebAssembly#getting-started[Getting Started] section, watch some of the https://github.com/golang/go/wiki/WebAssembly#go-webassembly-talks[Go WebAssembly talks], |
Justin Clift | 7c4f094 | 2019-04-27 20:28:45 +1000 | [diff] [blame] | 24 | then take a look at the https://github.com/golang/go/wiki/WebAssembly#further-examples[Further examples] below. |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 25 | ********************************************************************** |
| 26 | |
Justin Clift | bb1ad3d | 2018-10-26 02:35:20 +1100 | [diff] [blame] | 27 | |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 28 | # Getting Started |
| 29 | |
| 30 | This page assumes a functional Go 1.11 or newer installation. For |
| 31 | troubleshooting, see the https://github.com/golang/go/wiki/InstallTroubleshooting[Install Troubleshooting] |
| 32 | page. |
| 33 | |
| 34 | To compile a basic Go package for the web: |
| 35 | |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 36 | ```go |
| 37 | package main |
| 38 | |
| 39 | import "fmt" |
| 40 | |
| 41 | func main() { |
| 42 | fmt.Println("Hello, WebAssembly!") |
| 43 | } |
| 44 | ``` |
| 45 | |
| 46 | Set `GOOS=js` and `GOARCH=wasm` environment variables to compile |
| 47 | for WebAssembly: |
| 48 | |
| 49 | ```sh |
| 50 | $ GOOS=js GOARCH=wasm go build -o main.wasm |
| 51 | ``` |
| 52 | |
| 53 | That will build the package and produce an executable WebAssembly |
| 54 | module file named main.wasm. The .wasm file extension will make it |
| 55 | easier to serve it over HTTP with the correct Content-Type header |
| 56 | later on. |
| 57 | |
| 58 | To execute main.wasm in a browser, we'll also need a JavaScript |
| 59 | support file, and a HTML page to connect everything together. |
| 60 | |
| 61 | Copy the JavaScript support file: |
| 62 | |
| 63 | ```sh |
| 64 | $ cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" . |
| 65 | ``` |
| 66 | |
| 67 | Create an `index.html` file: |
| 68 | |
| 69 | ```HTML |
| 70 | <html> |
| 71 | <head> |
| 72 | <meta charset="utf-8"> |
| 73 | <script src="wasm_exec.js"></script> |
| 74 | <script> |
| 75 | const go = new Go(); |
| 76 | WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => { |
| 77 | go.run(result.instance); |
| 78 | }); |
| 79 | </script> |
| 80 | </head> |
| 81 | <body></body> |
| 82 | </html> |
| 83 | ``` |
| 84 | |
| 85 | If your browser doesn't yet support `WebAssembly.instantiateStreaming`, |
| 86 | you can use a https://github.com/golang/go/blob/b2fcfc1a50fbd46556f7075f7f1fbf600b5c9e5d/misc/wasm/wasm_exec.html#L17-L22[polyfill]. |
| 87 | |
| 88 | Then serve the three files (`index.html`, `wasm_exec.js`, and |
| 89 | `main.wasm`) from a web server. For example, with |
| 90 | https://github.com/shurcooL/goexec#goexec[`goexec`]: |
| 91 | |
| 92 | ```sh |
| 93 | $ goexec 'http.ListenAndServe(":8080", http.FileServer(http.Dir(".")))' |
| 94 | ``` |
| 95 | |
Christopher | 65a1569 | 2019-06-09 10:40:09 +0200 | [diff] [blame] | 96 | Or use your own https://play.golang.org/p/pZ1f5pICVbV[basic HTTP server command]. |
| 97 | |
Christopher | 6be57f4 | 2019-06-10 20:37:57 +0200 | [diff] [blame] | 98 | Note: for the `goexec` command to work on Unix-like systems, you must https://golang.org/doc/install#tarball[add the path environment variable] for Go to your shell's `profile`. Go's getting started guide explains this: |
| 99 | |
Christopher | 65a1569 | 2019-06-09 10:40:09 +0200 | [diff] [blame] | 100 | > Add /usr/local/go/bin to the PATH environment variable. You can do this by adding this line to your /etc/profile (for a system-wide installation) or $HOME/.profile: |
| 101 | |
| 102 | > `export PATH=$PATH:/usr/local/go/bin` |
| 103 | |
| 104 | > Note: changes made to a profile file may not apply until the next time you log into your computer |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 105 | |
| 106 | Finally, navigate to http://localhost:8080/index.html, open the |
| 107 | JavaScript debug console, and you should see the output. You can |
| 108 | modify the program, rebuild `main.wasm`, and refresh to see new |
| 109 | output. |
| 110 | |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 111 | # Executing WebAssembly with Node.js |
| 112 | |
| 113 | It's possible to execute compiled WebAssembly modules using Node.js |
| 114 | rather than a browser, which can be useful for testing and automation. |
| 115 | |
| 116 | With Node installed and in your `PATH`, set the `-exec` flag to the |
| 117 | location of `go_js_wasm_exec` when you execute `go run` or `go test`. |
| 118 | |
| 119 | By default, `go_js_wasm_exec` is in the `misc/wasm` directory of your |
| 120 | Go installation. |
| 121 | |
| 122 | ``` |
| 123 | $ GOOS=js GOARCH=wasm go run -exec="$(go env GOROOT)/misc/wasm/go_js_wasm_exec" . |
| 124 | Hello, WebAssembly! |
| 125 | $ GOOS=js GOARCH=wasm go test -exec="$(go env GOROOT)/misc/wasm/go_js_wasm_exec" |
| 126 | PASS |
| 127 | ok example.org/my/pkg 0.800s |
| 128 | ``` |
| 129 | |
| 130 | Adding `go_js_wasm_exec` to your `PATH` will allow `go run` and `go test` to work for `js/wasm` without having to manually provide the `-exec` flag each time: |
| 131 | |
| 132 | ``` |
| 133 | $ export PATH="$PATH:$(go env GOROOT)/misc/wasm" |
| 134 | $ GOOS=js GOARCH=wasm go run . |
| 135 | Hello, WebAssembly! |
| 136 | $ GOOS=js GOARCH=wasm go test |
| 137 | PASS |
| 138 | ok example.org/my/pkg 0.800s |
| 139 | ``` |
| 140 | |
Agniva De Sarker | 2462de6 | 2019-06-14 22:40:11 +0530 | [diff] [blame] | 141 | ## Running tests in the browser |
| 142 | |
| 143 | You can also use https://github.com/agnivade/wasmbrowsertest[wasmbrowsertest] to run tests inside your browser. It automates the job of spinning up a webserver and uses headless Chrome to run the tests inside it and relays the logs to your console. |
| 144 | |
| 145 | Same as before, just `go get github.com/agnivade/wasmbrowsertest` to get a binary. Rename that to `go_js_wasm_exec` and place it to your `PATH` |
| 146 | |
| 147 | ``` |
| 148 | $ mv $GOPATH/bin/wasmbrowsertest $GOPATH/bin/go_js_wasm_exec |
| 149 | $ export PATH="$PATH:$GOPATH/bin" |
| 150 | $ GOOS=js GOARCH=wasm go test |
| 151 | PASS |
| 152 | ok example.org/my/pkg 0.800s |
| 153 | ``` |
Justin Clift | bb1ad3d | 2018-10-26 02:35:20 +1100 | [diff] [blame] | 154 | |
norunners | 6595042 | 2019-06-16 00:45:20 -0700 | [diff] [blame] | 155 | Alternatively, use the `exec` test flag. |
| 156 | ``` |
| 157 | $ GOOS=js GOARCH=wasm go test -exec="$GOPATH/bin/wasmbrowsertest" |
| 158 | ``` |
| 159 | |
Justin Clift | bb1ad3d | 2018-10-26 02:35:20 +1100 | [diff] [blame] | 160 | # Go WebAssembly talks |
| 161 | |
Justin Clift | bda8004 | 2018-11-28 15:47:34 +1100 | [diff] [blame] | 162 | * https://www.youtube.com/watch?v=4kBvvk2Bzis[Building a Calculator with Go and WebAssembly] (https://tutorialedge.net/golang/go-webassembly-tutorial/[Source code]) |
Justin Clift | bb1ad3d | 2018-10-26 02:35:20 +1100 | [diff] [blame] | 163 | * https://www.youtube.com/watch?v=iTrx0BbUXI4[Get Going with WebAssembly] |
| 164 | |
| 165 | |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 166 | # Interacting with the DOM |
| 167 | |
| 168 | See https://godoc.org/syscall/js. |
| 169 | |
Justin Clift | 8f6cb64 | 2019-04-04 01:57:36 +1100 | [diff] [blame] | 170 | Also: |
| 171 | |
| 172 | * An experimental new framework https://github.com/vugu/vugu[Vugu] is |
| 173 | worth trying out, if you're looking for something like VueJS. :smile: |
| 174 | |
norunners | 11eda2e | 2019-06-02 10:11:11 -0700 | [diff] [blame] | 175 | * https://github.com/norunners/vue[vue - The progressive framework for WebAssembly applications.] |
norunners | c206467 | 2019-04-19 08:54:26 -0700 | [diff] [blame] | 176 | |
Justin Clift | 8f6cb64 | 2019-04-04 01:57:36 +1100 | [diff] [blame] | 177 | * https://github.com/dennwc/dom[A library for streamlining DOM manipulation] |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 178 | is in development. |
| 179 | |
Justin Clift | 8f6cb64 | 2019-04-04 01:57:36 +1100 | [diff] [blame] | 180 | * There is a https://gowebapi.github.io/[binding generator] that can be used. |
Justin Clift | bb1ad3d | 2018-10-26 02:35:20 +1100 | [diff] [blame] | 181 | |
norunners | 11eda2e | 2019-06-02 10:11:11 -0700 | [diff] [blame] | 182 | * https://github.com/norunners/vert[vert - WebAssembly interop between Go and JS values.] |
| 183 | |
Justin Clift | 1dab479 | 2019-05-06 01:58:18 +1000 | [diff] [blame] | 184 | ## Canvas |
| 185 | |
| 186 | * A new https://github.com/markfarnan/go-canvas[canvas drawing library] - seems pretty efficient. |
| 187 | ** https://markfarnan.github.io/go-canvas/[Simple demo] |
Justin Clift | ff596d5 | 2019-04-03 17:41:23 +1100 | [diff] [blame] | 188 | |
Agniva De Sarker | fa41332 | 2019-06-03 01:26:17 +0530 | [diff] [blame] | 189 | # Configuring fetch options while using net/http |
| 190 | |
| 191 | You can use the net/http library to make HTTP requests from Go, and they will be converted to https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API[fetch] calls. However, there isn't a direct mapping between the fetch https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters[options] and the http https://golang.org/pkg/net/http/#Client[client] options. To achieve this, we have some special header values that are recognized as fetch options. They are - |
| 192 | |
| 193 | - `js.fetch:mode`: An option to the Fetch API mode setting. Valid values are: "cors", "no-cors", "same-origin", navigate". The default is "same-origin". |
| 194 | |
| 195 | - `js.fetch:credentials`: An option to the Fetch API credentials setting. Valid values are: "omit", "same-origin", "include". The default is "same-origin". |
| 196 | |
| 197 | - `js.fetch:redirect`: An option to the Fetch API redirect setting. Valid values are: "follow", "error", "manual". The default is "follow". |
| 198 | |
| 199 | So as an example, if we want to set the mode as "cors" while making a request, it will be something like: |
| 200 | |
| 201 | ```go |
| 202 | req, err := http.NewRequest("GET", "http://localhost:8080", nil) |
| 203 | req.Header.Add("js.fetch:mode", "cors") |
| 204 | if err != nil { |
| 205 | fmt.Println(err) |
| 206 | return |
| 207 | } |
| 208 | resp, err := http.DefaultClient.Do(req) |
| 209 | if err != nil { |
| 210 | fmt.Println(err) |
| 211 | return |
| 212 | } |
| 213 | defer resp.Body.Close() |
| 214 | // handle the response |
| 215 | ``` |
| 216 | |
| 217 | Please feel free to subscribe to https://github.com/golang/go/issues/26769[#26769] for more context and possibly newer information. |
| 218 | |
Justin Clift | bb1ad3d | 2018-10-26 02:35:20 +1100 | [diff] [blame] | 219 | # Editor configuration |
| 220 | |
Justin Clift | fb2e83b | 2019-01-24 02:27:49 +1100 | [diff] [blame] | 221 | * https://github.com/golang/go/wiki/Configuring-GoLand-for-WebAssembly[Configuring GoLand and Intellij Ultimate for WebAssembly] - Shows the exact steps needed for getting Wasm working in GoLand and Intellij Ultimate |
Justin Clift | bb1ad3d | 2018-10-26 02:35:20 +1100 | [diff] [blame] | 222 | |
| 223 | |
| 224 | # WebAssembly in Chrome |
| 225 | |
| 226 | If you run a newer version of Chrome there is a flag (`chrome://flags/#enable-webassembly-baseline`) to enable Liftoff, their new compiler, which should significantly improve load times. Further info https://chinagdg.org/2018/08/liftoff-a-new-baseline-compiler-for-webassembly-in-v8/[here]. |
| 227 | |
| 228 | |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 229 | # Debugging |
| 230 | |
| 231 | WebAssembly doesn't *yet* have any support for debuggers, so you'll |
| 232 | need to use the good 'ol `println()` approach for now to display |
| 233 | output on the JavaScript console. |
| 234 | |
| 235 | An official https://github.com/WebAssembly/debugging[WebAssembly Debugging Subgroup] |
| 236 | has been created to address this, with some initial investigation and |
| 237 | proposals under way: |
| 238 | |
| 239 | * https://fitzgen.github.io/wasm-debugging-capabilities/[WebAssembly Debugging Capabilities Living Standard] |
| 240 | (https://github.com/fitzgen/wasm-debugging-capabilities[source code for the doc]) |
| 241 | * https://yurydelendik.github.io/webassembly-dwarf/[DWARF for WebAssembly Target] |
| 242 | (https://github.com/yurydelendik/webassembly-dwarf/[source code for the doc]) |
| 243 | |
| 244 | Please get involved and help drive this if you're interested in the Debugger side of things. :smile: |
| 245 | |
Justin Clift | fb68848 | 2019-05-31 14:53:28 +1000 | [diff] [blame] | 246 | ## Analysing the structure of a WebAssembly file |
| 247 | |
| 248 | https://wasdk.github.io/wasmcodeexplorer/[WebAssembly Code Explorer] is useful for visualising the structure of a WebAssembly file. |
| 249 | |
| 250 | * Clicking on a hex value to the left will highlight the section it is part of, and the corresponding text representation on the right |
| 251 | * Clicking a line on the right will highlight the hex byte representations for it on the left |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 252 | |
Justin Clift | bb1ad3d | 2018-10-26 02:35:20 +1100 | [diff] [blame] | 253 | # Known bug(s) |
| 254 | |
Justin Clift | b910f04 | 2018-11-09 11:50:27 +1100 | [diff] [blame] | 255 | Go releases prior to 1.11.2 https://github.com/golang/go/issues/27961[have a bug] which can generate incorrect wasm code in some (rare) circumstances. |
Justin Clift | bb1ad3d | 2018-10-26 02:35:20 +1100 | [diff] [blame] | 256 | |
| 257 | If your Go code compiles to wasm without problem, but produces an error like this when run in the browser: |
| 258 | |
| 259 | ``` |
| 260 | CompileError: wasm validation error: at offset 1269295: type mismatch: expression has type i64 but expected f64 |
| 261 | ``` |
| 262 | |
| 263 | Then you're probably hitting this error. |
| 264 | |
Justin Clift | b910f04 | 2018-11-09 11:50:27 +1100 | [diff] [blame] | 265 | The solution is to upgrade to Go 1.11.2 or later. |
Justin Clift | bb1ad3d | 2018-10-26 02:35:20 +1100 | [diff] [blame] | 266 | |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 267 | |
| 268 | # Further examples |
| 269 | |
| 270 | ## General |
| 271 | * https://github.com/agnivade/shimmer[Shimmer] - Image transformation in wasm using Go |
| 272 | |
| 273 | ## Canvas (2D) |
| 274 | * https://github.com/stdiopt/gowasm-experiments[GoWasm Experiments] - Demonstrates |
| 275 | working code for several common call types |
| 276 | ** https://stdiopt.github.io/gowasm-experiments/bouncy[bouncy] |
| 277 | ** https://stdiopt.github.io/gowasm-experiments/rainbow-mouse[rainbow-mouse] |
| 278 | ** https://stdiopt.github.io/gowasm-experiments/repulsion[repulsion] |
Justin Clift | 41abc96 | 2018-10-26 00:25:04 +1100 | [diff] [blame] | 279 | ** https://stdiopt.github.io/gowasm-experiments/bumpy[bumpy] - Uses the 2d canvas, and a 2d physics engine. Click around on the screen to create objects then watch as gravity takes hold! |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 280 | ** https://stdiopt.github.io/gowasm-experiments/arty/client[arty] |
Justin Clift | d62b562 | 2019-06-24 03:07:25 +1000 | [diff] [blame] | 281 | ** https://stdiopt.github.io/gowasm-experiments/hexy[hexy] (**new**) |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 282 | * https://github.com/djhworld/gomeboycolor-wasm[Gomeboycolor-wasm] |
| 283 | ** WASM port of an experimental Gameboy Color emulator. The https://djhworld.github.io/post/2018/09/21/i-ported-my-gameboy-color-emulator-to-webassembly/[matching blog post] |
| 284 | contains some interesting technical insights. |
Justin Clift | d62b562 | 2019-06-24 03:07:25 +1000 | [diff] [blame] | 285 | * https://justinclift.github.io/tinygo_canvas2/[TinyGo canvas] |
| 286 | ** This is compiled with https://tinygo.org[TinyGo] instead of standard go, resulting in a **19.37kB (compressed)** wasm file. |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 287 | |
| 288 | ## WebGL canvas (3D) |
| 289 | * https://bobcob7.github.io/wasm-basic-triangle/[Basic triangle] (https://github.com/bobcob7/wasm-basic-triangle[source code]) - Creates a basic triangle in WebGL |
| 290 | * https://bobcob7.github.io/wasm-rotating-cube/[Rotating cube] (https://github.com/bobcob7/wasm-rotating-cube[source code]) - Creates a rotating cube in WebGL |
| 291 | * https://stdiopt.github.io/gowasm-experiments/splashy[Splashy] (https://github.com/stdiopt/gowasm-experiments/tree/master/splashy[source code]) - Click around on the screen to generate paint... |
| 292 | |
Justin Clift | 1322f1a | 2018-11-02 14:44:21 +1100 | [diff] [blame] | 293 | # Reducing the size of Wasm files |
| 294 | |
| 295 | At present, Go generates large Wasm files, with the smallest possible size being around ~2MB. If your Go code imports libraries, this file size can increase dramatically. 10MB+ is common. |
| 296 | |
| 297 | There are two main ways (for now) to reduce this file size: |
| 298 | |
Johan Brandhorst | bee185a | 2019-04-18 12:18:46 +0100 | [diff] [blame] | 299 | 1. Manually compress the .wasm file. |
| 300 | a. Using `gz` compression reduces the ~2MB (minimum file size) example WASM file down to around 500kB. It may be better to use https://github.com/google/zopfli[Zopfli] to do the gzip compression, as it gives better results than `gzip --best`, however it does take much longer to run. |
| 301 | b. Using https://github.com/google/brotli[Brotli] for compression, the file sizes are markedly better than both Zopfli and `gzip --best`, and compression time is somwhere inbetween the two, too. |
Justin Clift | 1322f1a | 2018-11-02 14:44:21 +1100 | [diff] [blame] | 302 | |
Justin Clift | 4f39c8b | 2019-04-18 20:58:25 +1000 | [diff] [blame] | 303 | Examples from https://github.com/johanbrandhorst[@johanbrandhorst] |
| 304 | |
| 305 | **Example 1** |
Johan Brandhorst | d2de0d4 | 2019-04-18 12:28:24 +0100 | [diff] [blame] | 306 | [width="25%",cols="^m,e,e",frame="topbot",options="header"]] |
Justin Clift | 4f39c8b | 2019-04-18 20:58:25 +1000 | [diff] [blame] | 307 | |======= |
Johan Brandhorst | d2de0d4 | 2019-04-18 12:28:24 +0100 | [diff] [blame] | 308 | | Size | Command | Compression time |
| 309 | |16M | (uncompressed size) | N/A |
| 310 | |2.4M | `brotli -o test.wasm.br test.wasm` | 53.6s |
| 311 | |3.3M | `go-zopfli test.wasm` | 3m 2.6s |
| 312 | |3.4M | `gzip --best test.wasm` | 2.5s |
| 313 | |3.4M | `gzip test.wasm` | 0.8s |
Justin Clift | 4f39c8b | 2019-04-18 20:58:25 +1000 | [diff] [blame] | 314 | |======= |
| 315 | |
| 316 | **Example 2** |
Johan Brandhorst | d2de0d4 | 2019-04-18 12:28:24 +0100 | [diff] [blame] | 317 | [width="25%",cols="^m,e,e",frame="topbot",options="header"]] |
Justin Clift | 4f39c8b | 2019-04-18 20:58:25 +1000 | [diff] [blame] | 318 | |======= |
Johan Brandhorst | d2de0d4 | 2019-04-18 12:28:24 +0100 | [diff] [blame] | 319 | | Size | Command | Compression time |
| 320 | |2.3M | (uncompressed size) | N/A |
| 321 | |496K | `brotli -o main.wasm.br main.wasm` | 5.7s |
| 322 | |640K | `go-zopfli main.wasm` | 16.2s |
| 323 | |660K | `gzip --best main.wasm` | 0.2s |
| 324 | |668K | `gzip main.wasm` | 0.2s |
Justin Clift | 4f39c8b | 2019-04-18 20:58:25 +1000 | [diff] [blame] | 325 | |======= |
| 326 | |
Johan Brandhorst | bee185a | 2019-04-18 12:18:46 +0100 | [diff] [blame] | 327 | Use something like https://github.com/lpar/gzipped to automatically serve compressed files with correct headers, when available. |
| 328 | |
Justin Clift | b0fc077 | 2019-05-09 08:52:37 +1000 | [diff] [blame] | 329 | **2.** Use https://github.com/tinygo-org/tinygo[TinyGo] to generate the Wasm file instead. |
Justin Clift | 626e3ea | 2019-05-02 17:53:30 +1000 | [diff] [blame] | 330 | |
| 331 | TinyGo supports a subset of the Go language targeted for embedded devices, and has a WebAssembly output target. |
| 332 | |
Justin Clift | b0fc077 | 2019-05-09 08:52:37 +1000 | [diff] [blame] | 333 | While it does have limitations (not yet a full Go implementation), it is still fairly capable and the generated Wasm files are... tiny. ~10kB isn't unusual. The "Hello world" example is 575 bytes. If you `gz -6` that, it drops down to 408 bytes. :wink: |
Justin Clift | 626e3ea | 2019-05-02 17:53:30 +1000 | [diff] [blame] | 334 | |
| 335 | This project is also very actively developed, so its capabilities are expanding out quickly. See https://tinygo.org/webassembly/webassembly/ for more information on using WebAssembly with TinyGo. |
Justin Clift | c1b6885 | 2018-10-26 00:23:01 +1100 | [diff] [blame] | 336 | |
| 337 | # Other WebAssembly resources |
| 338 | |
norunners | c206467 | 2019-04-19 08:54:26 -0700 | [diff] [blame] | 339 | * https://github.com/mbasso/awesome-wasm[Awesome-Wasm] - An extensive list of further Wasm resources. Not Go specific. |