Erstellen einer WebAssembly Anwendung mit Go

Erstellen einer WebAssembly Anwendung mit Go

WebAssembly, kurz Wasm, ist ein binäres Programmformat für die Ausführung einer Anwendung im Web-Browser. Hochsprachen wie C/C++/Rust und eben auch Go sollen Wasm Dateien direkt als Zielformat erzeugen. Somit können Anwendungsentwickler die gleiche Programmiersprache server- wie auch clientseitig einsetzen.

Ziel ist eine echte, performante Alternative zu JavaScript in Hinblick auf Lade- und Ausführungsgeschwindigkeit zu schaffen.

Die WebAssembly Spezifikation wird innerhalb einer W3C Community Group und der WebAssembly Working Group entwickelt und wird durch die 4 großen Web-Browser bereits unterstützt (Firefox, Chrome, Safari und Edge).

The mission of the WebAssembly Working Group is to standardize a size- and load-time-efficient format and execution environment, allowing compilation to the web with consistent behavior across a variety of implementations.

Die WebAssembly Internetseite führt 4 Merkmale für Wasm auf:

  • Effizient und Schnell
  • Sicher
  • Offen und debuggingfähig
  • Teil der “open web platform”

Also Grund genug sich das mal anzuschauen ;-)

Vorbedingungen

Seit Version 1.11 unterstützt Go die direkte Ausgabe von WebAssembly Artefakten. Man sollte also prüfen ob man eine aktuelle Go-Version installiert hat.

go version

Ist dies nicht der Fall kann eine aktuelle Version von der Go-Downloadseite bezogen und installiert werden. Falls man bei oder während der Installation Probleme hat findet man eine InstallTroubleshooting Seite bei GitHub.

Erstes Einfaches Beispiel

In folgendem Beispiel soll ein einfacher String ausgegeben werden. Hierzu legt man im Go Workspace-Verzeichnis die Datei main.go an:

package main

func main() {
	println("Hello, WebAssembly!")
}

Wie beim jedem Cross-Compiling Vorgang bei Go müssen die zwei Umgebungsvariablen

  • GoARCH
  • GoOS

gesetzt werden. Die Architektur (GoARCH) muss für ein WASM-Kompilat auf wasm und das Betriebssystem (GoOS) auf js gesetzt werden. Somit kann man mit folgendem Befehl eine WASM Datei (test.wasm) aus der oberen Go Datei erstellen.

GoARCH=wasm GoOS=js go build -o test.wasm main.go

Die Dateiendung .wasm macht dahingehend Sinn, da wir diese Datei über einen WebServer mit dem richtigen Content-Type application/wasm ausliefern müssen (ansonsten blockieren Web-Browser die Ausführung) und eine Konfiguration in einem solchen Fall (eventuell) einfacher fällt.

Jetzt wird noch eine HTML Datei (index.html im Root Verzeichnis der Anwendung) benötigt, mit deren Hilfe die WASM Umgebung im Browser gestartet wird. Referenziert werden muss die Datei wasm_exec.js, die sich in der Go Distribution befindet (“JavaScript support file”).

Die Support-Datei kann mit folgendem Kommando in das Anwendungsverzeichnis kopiert werden:

cp $(go env GoROOT)/misc/wasm/wasm_exec.js .

Mit der HTML Seite verbindet man die Einzelteile zu einer kompletten Anwendung. Die JS-Datei stellt die Brücke zwischen Browser/JavaScript und Go dar.

<html>
	<head>
		<meta charset="utf-8">
		<script src="wasm_exec.js"></script>
		<script>
		const go = new Go();
		WebAssembly.instantiateStreaming(fetch("test.wasm"),
			go.importObject).then((result) => {
				go.run(result.instance);
			}
		);
		</script>
	</head>
	<body></body>
</html>

Der Aufruf von WebAssembly.instantiateStreaming ruft eine native Browser-Methode auf, sollte dies nicht funktionieren wird ein Polyfill benötigt:

if (!WebAssembly.instantiateStreaming) { // polyfill
	WebAssembly.instantiateStreaming = async (resp, importObject) => {
		const source = await (await resp).arrayBuffer();
		return await WebAssembly.instantiate(source, importObject);
	};
}

Um die Anwendung im Browser zu testen müssen jetzt die Dateien (index.html, wasm_exec.js und natürlich test.wasm) ausgeliefert werden. Am Einfachsten geht dies mit Go selbst.

Hier wird goexec benutzt. Die Installation erfolgt über:

go get -u github.com/shurcooL/goexec

Nach der Goexec Installation kann der HTTP-Server mit folgendem Kommando gestartet werden:

goexec 'http.ListenAndServe(":8080", http.FileServer(http.Dir(".")))'

Jetzt muss man nur noch http://localhost:8080/index.html aufrufen und die Debug Konsole öffnen!

Firefox Debug Console

Firefox Debug Console

Das komplette Beispiel kann auch in GitHub gefunden werden.

22.01.2019

 

Kennen Sie schon das Buch zum Thema?

Der praktische Soforteinstieg für Developer und Softwarearchitekten, die direkt mit Go produktiv werden wollen.

  • Von den Sprachgrundlagen bis zur Qualitätssicherung
  • Architekturstil verstehen und direkt anwenden
  • Idiomatic Go, gRPC, Go Cloud Development Kit
  • Cloud-native Anwendungen erstellen
Microservices mit Go Buch

zur Buchseite beim Rheinwerk Verlag Rheinwerk Computing, ISBN 978-3-8362-7559-0 (als PDF, EPUB, MOBI und Papier)

Kontakt

Source Fellows GmbH

Source Fellows GmbH Logo

Lerchenstraße 31

72762 Reutlingen

Telefon: (0049) 07121 6969 802

E-Mail: info@source-fellows.com