Das Wissensportal für IT-Professionals. Entdecke die Tiefe und Breite unseres IT-Contents in exklusiven Themenchannels und Magazinmarken.

SIGS DATACOM GmbH

Lindlaustraße 2c, 53842 Troisdorf

Tel: +49 (0)2241/2341-100

kundenservice@sigs-datacom.de
Die WebAssembly-Technologie hat das Potenzial, das Monopol von JavaScript im Bereich Single-Page Apps (SPAs) zu brechen. Sprachen wie C++, Rust oder C# drängen in den Browser – und das ganz ohne Plug-in und auf allen Plattformen. Für Teams, die ein bestehendes Investment in den genannten Programmiersprachen haben, wäre die Weiternutzung von vorhandenem Wissen und Code ein großer Vorteil gegenüber einem Wechsel in Richtung JavaScript und darauf aufbauenden Frameworks. Der Artikel erklärt am Beispiel des Open-Source-Frameworks Blazor, wie WebAssembly für ein SPA-Framework genutzt werden kann. Ein Codebeispiel demonstriert, wie die heute noch vorhandenen Beschränkungen (z. B. kein DOM-Zugriff, kein direkter Netzwerkzugriff) durch Kombination von JavaScript und WebAssembly umgangen werden können.

  • 21.06.2019
  • Lesezeit: 15 Minuten
  • 76 Views

Wenn es um Programmierung im Browser geht, hatte JavaScript bis vor Kurzem ein Monopol. Es gibt zwar eine Auswahl an Sprachen und Werkzeugen wie TypeScript [TypeS] oder Babel [Babel], die Herausforderungen rund um JavaScript, wie Lücken im Typsystem und Rückwärtskompatibilität zu alten Browser- und JavaScript-Versionen, lösen. In der einen oder anderen Form lief es im Browser aber bisher immer auf JavaScript hinaus.

Das alleine wäre noch kein Problem. JavaScript beziehungsweise dessen standar­disierter Sprachkern ECMAScript [ECMAS] hat sich in den letzten Jahren zu einer zeitgemäßen, funktionellen Programmiersprache gemausert. Für rechenintensive Anwendungen wie CAD-Systeme oder aufwendige Browser-Spiele ist JavaScript aber weniger gut geeignet, da die dort notwendige Performanz nicht erreicht werden kann.

Solche Anwendungen sind das Revier von Systemprogrammiersprachen wie C++ oder Rust [Rust]. Ihr Nachteil ist die schwierige Verteilbarkeit. Der Quellcode ist zwar oft plattformunabhängig, die nativen, ausführbaren Binärdateien sind es aber nicht. Darüber hinaus gibt es Hürden bei der Softwareverteilung, da Benutzer und Administratoren Angst vor Schadsoftware haben.

Aufbrechen des JavaScript-Monopols

Ideal wäre ein System, das die Vorteile des Browsers hinsichtlich Softwareverteilung und Sandboxing [Wiki-a] mit der Performanz nativer Programme verbindet. Aus diesem Gedanken entstand vor einigen Jahren das Projekt asm.js [asmjs]. Dabei handelt sich um ein Subset von JavaScript, das von Browsern Ahead of Time (AOT, [Wiki-b]) in effizienten Maschinencode kompiliert werden kann. Compiler von Systemprogrammiersprachen wie C++ können asm.js statt ausführbarem Code erzeugen und so Programmteile, die besonders effizient laufen müssen, in den Browser bringen. JavaScript spielt bei asm.js aber immer noch eine entscheidende Rolle.

Der nächste Schritt nach asm.js war,
JavaScript als Format für ausführbaren Code zu ersetzen, da die Sprache nie dafür gedacht war und sich daher nur bedingt dafür eignet. Es wurde das WebAssembly-Projekt (kurz WASM, [Wasm]) aus der Taufe gehoben. Ziel des Projekts ist es, ein vom World Wide Web Consor­tium (W3C) standardisiertes, portables, effizientes Binärformat für ausführbaren Code zu schaffen, in das Quellcode von Systemprogrammiersprachen übersetzt werden kann. JavaScript-Interoperabi­lität spielt eine große Rolle, damit WASM sich gut für den Betrieb im Browser eignet. Streng genommen könnte WASM auch außerhalb des Browsers für portable Programme genutzt werden (ähnlich wie Java­Script in Verbindung mit Node.js [Nodejs]). Dieser Artikel betrachtet aber nur die Anwendung von WASM im Browser.

Die Browser-Hersteller sprangen auf den WASM-Zug auf und heute implementieren alle großen Browser eine Ausführungsumgebung für WASM-Code sowohl am Desktop als auch auf mobilen Plattformen [CanIuse]. Auch wenn WASM relativ jung ist, gibt es bereits eine Menge beeindruckender Beispiele, die das Potenzial der Technologie zeigen (z. B. AutoCAD Web App [Frie18]).

WASM kann JavaScript im Moment noch nicht vollständig ersetzen, da die Plattform in diesem Zusammenhang eine wesentliche Einschränkung hat: Sie kann nicht direkt mit dem Browser-DOM interagieren. WASM braucht also JavaScript, um etwas auf dem Bildschirm darzustellen. Für die Rechenlogik ist WASM aber nicht mehr auf JavaScript angewiesen. Sprachen wie C++ oder Rust brauchen diesen Umweg nicht mehr. Das Monopol von JavaScript ist damit zumindest in Teilbereichen gebrochen.

.NET und C# im Browser

Die .NET-Plattform mit der darauf aufbauenden Sprache C# spielt in der Softwareentwicklung eine große Rolle. C# hat im TIOBE-Index der meist verbreiteten Programmiersprachen seit vielen Jahren einen Stammplatz in den Top 10 [TIOBE]. Was die Beliebtheit anbelangt, erreicht C# ebenfalls sehr gute Werte (siehe z. B. den „Stack Overflow Developer Survey 2018“ [SO]). Seit dem Erscheinen der .NET Core-Version [.NET] ist die Plattform auch plattformunabhängig und Open Source.

Durch die weite Verbreitung und Beliebtheit liegt es nahe, dass es eine große Personengruppe gibt, die sich .NET und C# als Programmierplattform für Browser-Anwendungen wünschen würde. Einen Versuch in diese Richtung hat Microsoft vor Jahren mit Silverlight [Silverl] gewagt. Da Silverlight jedoch ein Browser-Plug-in vorausgesetzt hat und Plug-ins in Browsern in Verruf gekommen sind, kann man diesen Versuch als gescheitert ansehen. Silverlight wird zwar von Microsoft noch bis 2021 offiziell unterstützt, für Neuprojekte ist aber dringend davon abzuraten.

WASM öffnet eine ganz neue Tür für die Idee, .NET und C# in den Browser zu bringen. Auf unterster Ebene ist die .NET-Laufzeitumgebung mit C++ entwickelt [CoreCLR]. C++ kann nach WASM kompiliert werden. Warum also nicht die .NET-Plattform mithilfe von WASM ohne Plug-in in den Browser bringen? Genau diese Frage hat sich das Team von Mono, einer von Microsoft unterstützten Open-Source-Implementierung von .NET, gestellt. Im August 2017 konnte ein erster Prototyp eines „Hello World“-Programms in C# auf Basis von WASM gezeigt werden [Mono].

Die Mono-Implementierung für WASM muss C# nicht direkt in WASM-Code übersetzen. Die .NET-Laufzeitumgebung wird in WASM ausgeführt und übernimmt das Laden und Ausführen (interpretiert oder kompiliert) von .NET-IL-Code. Im unten näher erläuterten Blazor-Framework führt Mono ganz normale .NET-DLLs aus, die unverändert auch auf Windows, Mac OS oder Linux ausführt werden könnten (siehe dazu auch Abbildung 1). Diese Architektur ist für viele Entwicklungsteams sehr interessant, da Wiederverwendung von vorhandenem Code und Wissen im Browser ohne die Notwendigkeit einer kompletten Neuentwicklung auf anderer, technischer Basis in greifbare Nähe rückt.

Abb. 1: Ladeprozess von .NET auf WASM im Browser

Das Blazor-Framework

Die .NET-Laufzeitumgebung auf WASM zum Laufen zu bringen, ist nur ein erster Schritt. Damit diese Technik auch nutzbringend eingesetzt werden kann, braucht es mehr. Schließlich kann WASM wie erwähnt den DOM nicht manipulieren und hat daher kein UI. Um .NET in der Praxis für Browserprogrammierung verwenden zu können, braucht es ein spezialisiertes Framework, das das Zusammenspiel aus .NET, WASM und DOM einfach und effizient genug für den Einsatz in der täglichen Entwicklungspraxis macht.

Vor diesem Hintergrund ist das Open-Source-Projekt Blazor [Blazor] entstanden. Es wird zwar primär von Microsoft vorangetrieben und finanziert, Community-Beiträge wurden aber von Anfang an akzeptiert und sind keine Seltenheit. Blazor baut auf der Mono-Implementierung von .NET auf WASM auf und fügt Komponenten hinzu, die für die Entwicklung von Single-Page Apps (SPAs) notwendig sind. Dazu gehören unter anderem:

  • Eine Template Markup Language zum dynamischen Aufbau von HTML inklusive Data Binding. Blazor greift hier – wie der Name schon vermuten lässt – auf die in .NET Core bereits vorhandene Razor-Syntax [Razor] zurück.
  • System für den modularen, komponentenorientierten Aufbau von Benutzerschnittstellen.
  • Client-seitiger Router.
  • Dependency Injection-System.
  • Interoperabilitätsschicht für JavaScript.
  • Vorlagen und Werkzeuge für die Entwicklungsumgebung Visual Studio.

Eine komplette Einführung in die APIs von Blazor und die zugehörige Template-Sprache würde den Rahmen dieses Artikels sprengen. Listing 1 zeigt exemplarisch ein einfaches Template mit verschiedenen Data Binding-Mechanismen. Die Möglichkeiten von Blazor gehen weit über den gezeigten Code hinaus. Er soll an dieser Stelle nur dazu dienen, einen Eindruck vom Grundprinzip der Programmierung mit Blazor zu veranschaulichen.

Listing 1: Einfaches Razor-Template mit Data Binding und C#-Logik

Die Funktionsweise von Blazor

Mit Blazor werden Geschäfts- und UI-Logik in C# geschrieben. Vorhandener, .NET-Standard-kompatibler Code kann wiederverwendet werden.

Für die Darstellung des UI werden der Browser-DOM und damit zusammenhängende Technologien wie CSS verwendet. Die Razor-Templates werden in C#-Code kompiliert. Bei Benutzerschnittstellen, die sich aus einem Algorithmus ergeben, kann man auf Templates auch verzichten und die Blazor-Programmierschnittstelle nutzen, um die UI programmatisch zu erzeugen. Abbildung 2 zeigt dieses Prinzip anhand eines Screen­shots von Visual Studio.

Abb. 2: Übersetzung von Razor-Templates in C#

Blazor bringt eine JavaScript-Bibliothek mit, die die Brücke zwischen DOM, JavaScript und C#-Code in WASM bildet. Wenn ein Benutzer zum Beispiel auf einen Button klickt, kümmert sich der JavaScript-Teil von Blazor um das Behandeln des Events und gibt den Aufruf über WASM an den C#-Code weiter. Manipuliert umgekehrt der C#-Code Daten, die über Data Binding an das UI gekoppelt sind, kommuniziert die Blazor-Laufzeitumgebung automatisch mit ihrem JavaScript-Teil. Dieser führt dann die entsprechenden Änderungen am DOM durch. Die Blazor-Laufzeitumgebung enthält dafür ein Kommunikationsprotokoll für die effiziente Übertragung von Events und DOM-Änderungen zwischen WASM und JavaScript. Abbildung 3 stellt diese Architektur als Sequenzdiagramm dar.

Abb. 3: Zusammenspiel C#/WASM und JavaScript

In Abbildung 4 sieht man, wie der zugehörige Call Stack zum Zeitpunkt der DOM-Veränderung durch JavaScript aussieht. Beachten Sie, wie der JavaScript-Teil von Blazor das Click-Event entgegennimmt. Anschließend erfolgt die Behandlung des Events durch C#/WASM. Die sich aus der Verarbeitung ergebenden DOM-Änderungen werden am Ende wieder durch JavaScript durchgeführt.

Blazor nutzt auf unterster Ebene die Standardfunktionen für WASM-JavaScript-Interoperabilität. WASM basiert auf dem Konzept von linearem Speicher [WasmLM]. Speicherblöcke sind untypisierte Byte Arrays, auf die JavaScript- und WASM-Code zugreifen können. Über diesen einfachen Mechanismus muss die Kommunikation zwischen den beiden Welten laufen. Blazor lässt diese komplizierte Aufgabe für Entwicklungsteams verschwinden. Man kann sich ganz auf die Anwendungsentwicklung konzentrieren und hat komfortable Data Binding-Mechanismen zur Verfügung.

Abb. 4: Call Stack für Verarbeitung eines DOM-Events

Razor Components

WASM und die dafür in Mono hinzugefügte Unterstützung sind junge Technologien, die noch in den Kinderschuhen stecken. Es fehlen noch wichtige Bausteine wie ein vollwertiger Debugger oder AOT-Kompilierung von .NET-Code, die man bei einer kompletten Plattform eigentlich voraussetzen können sollte. Sowohl WASM als auch Mono für WASM haben die Produktionsreife noch nicht erreicht. Daher hat auch das darauf aufbauende Blazor erst Preview-Status und ist im Moment nicht für den Produktionsbetrieb geeignet. Es wird auch noch einige Zeit dauern, bis sich das ändert.

Das Programmiermodell von Blazor hat aber bereits viele Anhänger gefunden. Aus diesem Grund hat sich eine Variante des Blazor-Projekts entwickelt, die ohne WASM auskommt und daher schon mit .NET Core 3 im Herbst 2019 in einer produktiven Version erscheinen wird. Der Grundgedanke ist, dass die Logik nicht im Browser, sondern am Server ausgeführt wird. Daher wird diese Blazor-Variante manchmal als Server-Side Blazor [Ram18] bezeichnet. Ihr offizieller Name lautet Razor Components.

Sie baut auf dem Kommunikationsprotokoll auf, das eigentlich für die Kommunikation zwischen WASM und JavaScript entwickelt wurde. Bei Server-Side Blazor läuft die Logik am Server mit ASP.NET Core, der Code zur Interaktion mit dem DOM im Browser und die Kommunikation erfolgt über Websockets. WASM und Mono spielen bei Server-Side Blazor keine Rolle.

Abbildung 5 zeigt einen Screenshot einer Beispielanwendung mit Razor Components. Man sieht, wie zwischen Client und Server eine Websockets-Verbindung aufgebaut wird, über die die Kommunikation zwischen JavaScript- und C#-Teil von Blazor läuft.

Man kann bereits jetzt eine normale Blazor-Anwendung in Razor Components umwandeln, indem man nur wenige Zeilen Code anpasst. Diese Flexibilität ist besonders interessant, wenn man es mit unterschiedlich starken Endgeräten zu tun hat. Sind ausreichend Rechenleistung und gute WASM-Unterstützung vorhanden, kann man die WASM-basierte Variante von Blazor nutzen. Fehlt WASM oder ist das Endgerät eher leistungsschwach, übernimmt der Server die Ausführung der Programmlogik.

Abb. 5: Websocket-Verbindung zwischen Client und Blazor-Server

Fazit und Einschätzung

Blazor hat in der .NET-Programmiergemeinde für viel Aufsehen gesorgt. Viele Teams haben es mit großen C#-Codebasen zu tun. Ihnen fehlen aber Ressourcen für eine Neuentwicklung. Trotzdem streben sie zumindest mit Teilen ihrer Lösungen den Browser an. Blazor öffnet in dieser Hinsicht ganz neue Perspektiven.

Will man diesen Weg gehen, braucht man aber noch Geduld. Jetzt ist der richtige Zeitpunkt, um mit Blazor zu experimentieren, Prototypen zu bauen und die Auswirkung von .NET auf WASM auf die mittel- und langfristige Softwarearchitektur abzuschätzen. Ein produktives Projekt schon jetzt auf Blazor-Basis zu starten, wäre ein nicht zu unterschätzendes Risiko. Die Programmierschnittstelle und selbst einige Aspekte der Blazor-Architektur könnten sich noch ändern.

Auch wenn die Chancen meiner Einschätzung nach gut stehen, kann niemand mit Sicherheit sagen, ob Blazor größere Verbreitung finden wird. Auch was die Entwicklungsproduktivität angeht, muss man im Moment noch Abstriche in Kauf nehmen. Es gibt beispielsweise erst wenige UI-Komponenten (z. B. UI Control Libraries) und die Entwicklungswerkzeuge zeigen teilweise noch Entwicklungsbedarf.

Meiner Ansicht nach kommt dem Blazor-Projekt schon jetzt große Bedeutung zu, weil es beweist, dass eine Mainstream-Entwicklungsplattform wie .NET mit C# durch WASM ohne Plug-ins den Browser erobern kann. Noch ist JavaScript als Vermittler zwischen WASM und DOM notwendig. Es ist aber nicht in Stein gemeißelt, dass diese Einschränkung von WASM in Zukunft bestehen bleiben muss.

WASM ist meiner Einschätzung nach nicht der JavaScript-Killer. Das heute bestehende Monopol ist aber gebrochen und Entwicklerteams steht im Browser in Zukunft eine größere Auswahl an Programmiersprachen und Frameworks zur Verfügung.||

Weitere Informationen

[asmjs] http://asmjs.org/

[Babel] https://babeljs.io/

[Blazor] https://github.com/aspnet/Blazor

[CanIuse] https://caniuse.com/#feat=wasm

[CoreCLR] https://github.com/dotnet/coreclr

[ECMAS] https://www.ecma-international.org/ecma-262/

[Frie18] L. E. Friedman, Roundup: The AutoCAD Web App at Google I/O 2018, Autodesk, 28.5.2018, siehe: http://blogs.autodesk.com/autocad/autocad-web-app-google-io-2018/

[Mono] https://www.mono-project.com/news/2017/08/09/hello-webassembly/

[.NET] https://dotnet.microsoft.com/download

[Nodejs] https://nodejs.org/

[Ram18] D. Ramel, Server-Side Blazor to Ship in .NET Core 3.0, Visual Studio Magazine, 2018, https://visualstudiomagazine.com/articles/2018/10/03/blazor-update.aspx

[Razor] https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor

[Rust] https://www.rust-lang.org/

[Silverl] https://www.microsoft.com/silverlight/

[SO] Stack Overflow Developer Survey 2018, https://insights.stackoverflow.com/survey/2018/

[TIOBE] https://www.tiobe.com/tiobe-index/

[TypeS] http://www.typescriptlang.org/

[Wasm] https://webassembly.org/

[WasmLM] https://webassembly.org/docs/semantics/#linear-memory

[Wiki-a] https://de.wikipedia.org/wiki/Sandbox

[Wiki-b] https://de.wikipedia.org/wiki/Ahead-of-time-Compiler

. . .

Author Image
Zu Inhalten
Rainer Stropek ist IT-Unternehmer, Softwareentwickler, Trainer, Autor und Vortragender im Microsoft-Umfeld. Er ist seit 2010 MVP für Microsoft Azure und entwickelt mit seinem Team die Zeiterfassung für Dienstleistungsprofis: time cockpit.

Artikel teilen