WebAssembly – Webanwendungen auf der Überholspur

JavaScript dominiert die Entwicklung von Software im Browser. Es gibt aber immer wieder Herausforderer – aktuell beispielsweise WebAssembly.

Sprachen  –  85 Kommentare
WebAssembly [--] Webanwendungen auf der Überholspur

WebAssembly, kurz Wasm, soll helfen, Webanwendungen in puncto Geschwindigkeit näher an klassische Desktopanwendungen heranzubringen. Genau genommen ist WebAssembly eine Spezifikation, die eine Instruction Set Architecture definiert und ein Dateiformat spezifiziert. Die Instruction Set Architecture beschreibt einen (virtuellen) Computer. Das Dateiformat legt den Aufbau von WebAssembly-Modulen fest. Alle großen Browserhersteller haben die WebAssembly-Spezifikation im Frühjahr 2017 in ihren Browsern implementiert. Nur der Internet Explorer bleibt außen vor.

Der Browser lädt den zu WebAssembly kompilierten Code in Form von Modulen und führt ihn aus. Vorstellen kann man sich das wie ein Java-Applet, das vorab nach Java-Bytecode kompiliert wurde und später beim Abruf eine Java Virtual Machine (VM) ausführt. Java-Applets allerdings sind eine Erweiterung des Browsers, nicht Teil des Web. WebAssembly hingegen ist als Standard im Web-Ökosystem verankert. Es gehört nicht einem einzigen Unternehmen, das allein über die Weiterentwicklung bestimmt, sondern einer Gruppe bestehend aus Browser-Herstellern und Einzelpersonen.

Ein weiterer, wichtiger Unterschied ist die Möglichkeit, Wasm-Module nach JavaScript zu übersetzen. Im Binaryen-Toolkit gibt es dafür das Programm wasm2asm. Das ist für Browser gedacht, die keine WebAssembly-Unterstützung besitzen. Nach JavaScript konvertiert funktioniert das Wasm-Modul ohne WebAssembly-Support, allerdings etwas langsamer als in Browsern mit WebAssembly-Unterstützung.

Damit Entwickler WebAssembly-Module erzeugen können, benötigen sie einen Compiler, der das Wasm-Format versteht und Code nach WebAssembly kompilieren kann. Davon gibt es mittlerweile einige. Hervorzuheben sind C und C++ über Clang und Emscripten, Rust sowie das experimentelle C#-Framework Blazor.

Neben einem generellen Compiler-Support gibt es weitere Eigenschaften einer Toolchain, die beim Erstellen und Benutzen von Wasm-Modulen von Vorteil sind. WebAssembly unterstützt von Haus aus die Kommunikation mit der Host-Umgebung. Das heißt, man kann von einem Wasm-Modul aus JavaScript-Funktionen aufrufen und von JavaScript aus Wasm-Funktionen benutzen. Das Interface ist jedoch rudimentär. Anwender können nur solche Funktionen ex- und importieren, deren Rückgabewerte und Parameter entweder Integer oder IEEE-754-Floating-Point-Typen sind. Alles andere erfordert ein explizites Hinein- beziehungsweise Herauskopieren von JavaScript aus in den Wasm-Speicher. Sowohl Emscripten als auch Rust bieten Bibliotheken und Werkzeuge an, die eine Übergabe in beide Richtungen für viele und insbesondere komplexere Datenstrukturen übernehmen und damit die Kommunikation mit Wasm-Modulen erheblich vereinfachen.

Emscripten bietet hierfür zwei Methoden an: Web IDL und die Emscripten-Bibliothek Embind. Web IDL ist ein standardisiertes Format, das Web-APIs für alle Browser einheitlich spezifiziert. Web IDL definiert die JS/Wasm-Schnittstelle und übersetzt sie mit einem Skript in C++ und JavaScript. Die Embind-Bibliothek legt die Schnittstelle direkt im C++-Code mit Makros fest und implementiert sie.

Für Rust gibt es ebenfalls mehrere Bibliotheken (bei Rust "crates" genannt). Zwei bekannte Werkzeuge sind stdweb und wasm-bindgen. stdweb ist eine Bibliothek, die ausgewählte JavaScript- und Web-APIs in Rust verfügbar macht und eine unkomplizierte Möglichkeit schafft, Rust-Funktionen nach JavaScript zu exportieren. wasm-bindgen bietet das Gleiche an, generiert Web-APIs allerdings automatisch aus Web-IDL-Definitionen. Makros importieren und exportieren eigene Funktionen.