Blog

PWAs mit Blazor WebAssembly

Einsatzgebiete, Erfolgsgeschichten, Einschränkungen

Jun 14, 2023

Progressive Web Apps (PWAs) sind ein webbasiertes Anwendungsmodell. Einmal geschrieben, können sie auf allen Plattformen ausgeführt werden, auf denen ein halbwegs aktueller Webbrowser läuft.

Das Leben einer PWA beginnt in einem regulären Browsertab, sei es in Chrome, Edge, Firefox oder Safari. Dort laufen die Anwendungen selbst dann, wenn die Anwender:innen gerade offline sind. Mit dem passenden Browser lassen sich PWAs auch auf dem Gerät installieren, um einen noch schnelleren Zugriff auf sie zu erhalten: Das funktioniert unter Android und iOS, macOS, Linux und Windows.

Da es sich bei PWAs um Websites handelt, können sie ausschließlich Schnittstellen und Gerätefunktionen aufrufen, die im Web bereitgestellt werden. Glücklicherweise ist das Web spätestens seit der Einführung von HTML5 immer mächtiger geworden. Auch über die vergangenen Jahre kamen immer mehr Schnittstellen ins Web, um die Leistungsfähigkeit webbasierter Anwendungen noch weiter zu erhöhen, zuletzt über die Initiative „Project Fugu“.

Blazor in vier Ausprägungen

Da PWAs auf Webtechnologien aufsetzen, können sämtliche Bibliotheken und Frameworks auf ihre Schnittstellen zugreifen: Angular, React, Vue.js ganz ohne Framework, aber eben auch Microsofts Webframework Blazor, das es in verschiedenen Ausprägungen gibt:

  1. Bei Blazor WebAssembly wird der Anwendungscode komplett clientseitig ausgeführt.

  2. Bei Blazor Server wird die App auf einem Server ausgeführt, der die HTML-Fragmente rendert und per Socket-Verbindung zum Client überträgt. Der Client übermittelt sämtliche Benutzerinteraktionen an den Server, was zu erneutem Rendern führt.

  3. Bei Blazor Hybrid wird Blazor innerhalb einer MAUI-, Windows-Forms- oder WPF-Anwendung ausgeführt, läuft also nicht im Browser (vergleichbar mit Electron). Im Gegenzug können sämtliche plattformspezifischen Schnittstellen aufgerufen werden.

  4. Für .NET 8 wurde zudem noch Blazor United angekündigt, das die Vorteile von Blazor WebAssembly, Blazor Server und Razor Pages vereinen soll: HTML-Fragmente können auf dem Server vorgerendert und danach interaktiv weiterbetrieben werden, wahlweise auf dem Client oder dem Server [1].

Tabelle 1 stellt die Ansätze Blazor WebAssembly, Blazor Server und Blazor Hybrid anhand häufig gewünschter Kriterien für Webanwendungen gegenüber.

Für Progressive Web Apps kommt nur das Modell Blazor WebAssembly in Frage, denn nur dieser Ansatz unterstützt die Ausführbarkeit der Anwendung direkt im Browser in Kombination mit der Unterstützung von Offlineverfügbarkeit. Auf Wunsch lässt sich die Anwendung dennoch für Mobil- und Desktopbetriebssysteme verpacken, um sie über die althergebrachten Deployment-Wege wie App Stores oder Installer zu vertreiben. In diesem Fall ist dann auch der Aufruf sämtlicher plattformspezifischer Schnittstellen möglich. Ein weiterer Vorteil ergibt sich durch die einfache Skalierbarkeit, da die Anwendung auf dem Rechner des Clients ausgeführt wird. Bei Blazor Server muss der Server sämtliche Sessions verwalten können. Von Nachteil ist jedoch, dass auch der Programmcode auf den Rechner des Anwenders übertragen wird und somit nicht geheim gehalten werden kann, wie es für sämtliche Anwendungen gilt, deren Code an Anwender:innen übertragen wird.

Blazor WebAssembly Blazor Server Blazor Hybrid
Ausführbarkeit in Browsern + +
Unterstützung für Offlineverfügbarkeit + +
Paketierbarkeit für Mobile und Desktop + +
Aufrufbarkeit beliebiger plattformspezifischer Schnittstellen – (nur wenn verpackt) + (nur auf dem Server) +
Einfache Skalierbarkeit + +
Code kann geheimgehalten werden +

Tabelle 1: Vergleich der Blazor-Ausprägungen

Da Blazor WebAssembly den einzigen relevanten Ansatz zur Entwicklung von Progressive Web Apps darstellt, wird sich der Artikel allein auf diese Ausprägung konzentrieren. Für das zum Zeitpunkt des Verfassens noch nicht veröffentlichte Blazor United trifft zu, was in Tabelle 1 in der Spalte „Blazor WebAssembly“ steht, sofern die vorgerenderten Inhalte zustandslos sind und die übrige Interaktion clientseitig durchgeführt werden kann, andernfalls gilt die Spalte „Blazor Server“.

Referenzarchitektur Single Page Application

Blazor WebAssembly implementiert das von anderen Frameworks wie Angular, React oder Vue.js bekannte Architekturmuster der Single Page Application (SPA): Hierbei werden die erforderlichen Dateien (HTML, JavaScript, CSS, WebAssembly-Module, DLLs und weitere Assets wie Bilder oder Videos) beim Start der Anwendung zum Client übertragen. Die Quelldateien können dabei lokal zwischengespeichert werden, was die Anwendung grundsätzlich offlinefähig macht. Dieser Schritt lässt sich damit vergleichen, eine EXE-Datei inklusive all ihrer Abhängigkeiten auf den Computer der Anwender:innen zu übertragen. Nach dem Laden finden alle Interaktionen und Sichtwechsel clientseitig, also auf dieser Single Page, statt. Eine Kontaktaufnahme zum Server ist nicht erforderlich, was die Anwendung somit sehr performant macht.

Zum Austausch von Daten können Webschnittstellen über HTTPS oder WebSockets angesprochen werden, wie Abbildung 1 zeigt. Darüber hinaus stehen clientseitige Speichermethoden und Datenbanken zur Verfügung, sodass Anwendungsdaten auch offline angezeigt und bearbeitet werden können, eine passende Synchronisationslogik vorausgesetzt.

Abb. 1: Single-Page-App-Architektur mit Blazor WebAssemblyAbb. 1: Single-Page-App-Architektur mit Blazor WebAssembly

Progressive Web Apps: Installierbarkeit und Offlinefähigkeit

Progressive Web Apps sind ein Überbegriff für eine bestimmte Art Webanwendung. Sie sollen folgende Eigenschaften besitzen [2]:

  • Responsive: Sie passen sich an die verfügbaren Bildschirmabmessungen an (vom Smartphone bis zum 80-Zoll-Fernseher, wenn sinnvoll).

  • Linkable: Sie erlauben das Verweisen auf Zielzustände innerhalb der Anwendung über den URL (z. B. eine konkrete Seite oder einen gezielten Datensatz).

  • Discoverable: Sie sind unterscheidbar von normalen Websites.

  • Installable: Sie können dem Home-Bildschirm bzw. der Programmliste des Betriebssystems hinzugefügt werden.

  • App-like: Sie sehen so aus und verhalten sich wie plattformspezifische Apps.

  • Connectivity independent: Sie sind auch mit schwacher oder ohne Internetverbindung lauffähig, zumindest im Rahmen der Möglichkeiten.

  • Fresh: Sie sind trotz Offlinekopie immer so aktuell wie möglich.

  • Safe: Sie übertragen Inhalte nur über eine gesicherte Verbindung (HTTPS).

  • Re-engageable: Sie fordern zur Wiederverwendung der Anwendung per Pushnachricht auf.

  • Progressive: Sie schließen die Verwendung älterer/leistungsschwächerer Browser nicht aus.

Die Kernspezifikationen des Anwendungsmodells sind das Web Application Manifest, das das Aussehen und Verhalten der auf dem Gerät installierten PWA definiert, und die Service Workers, die unter anderem für die Offlineverfügbarkeit der Anwendung zuständig sind. Beide Spezifikationen werden vom World Wide Web Consortium (W3C) verwaltet.

Beim Web App Manifest [3] handelt es sich um eine JSON-basierte Datei (Listing 1), die unter anderem den Anzeigenamen der Anwendung (Eigenschaften name und short_name), das App-Icon (Eigenschaft icons) sowie den gewünschten Anzeigemodus (Eigenschaft display) definiert. Das Web Application Manifest wird in der index.html-Datei der Anwendung referenziert.

Listing 1

{
  "short_name": "EM",
  "name": "entwickler magazin",
  "theme_color": "white",
  "icons": [{ "src": "icon.png", "sizes": "512x512" }],
  "start_url": "./",
  "display": "standalone"
}

Durch die Verfügbarkeit des Web App Manifest lässt sich die PWA nun auf den Home-Bildschirm des Mobilgerätes (iOS, Android) beziehungsweise in die Programmliste des Desktopgerätes (macOS, Linux, Windows mit Chrome oder Edge) installieren. Von dort aus gestartet, erscheint die Webanwendung aufgrund des gewählten Anzeigemodus standalone wie eine plattformspezifische App: auf Mobilgeräten vollflächig, auf dem Desktop in einem eigenen Fenster, in beiden Fällen komplett ohne Browserstatusleisten. Vor Chromium 111 war für die Chromium-basierten Browser auch das Vorhandensein eines Service Workers verpflichtend; diese Bedingung ist jedoch entfallen.

 

ZUM NEWSLETTER

Regelmäßig News zur Konferenz und der .NET-Community

 

Die Service Workers [4] hingegen sind in JavaScript verfasste Skripte, die durch die Website registriert werden und danach die Rolle eines Controllers beziehungsweise Proxys übernehmen: Sie können auch ausgeführt werden, wenn die Website geschlossen ist, um Hintergrundaufgaben wie die Anzeige von Pushbenachrichtigungen oder die Synchronisierung von Daten durchzuführen.

Außerdem besitzt der Service Worker einen Cache, in dem er Antworten zu GET-Anfragen lokal zwischenspeichern kann. Darüber lässt sich die Offlineverfügbarkeit abbilden (Abb. 2): Nach Installation und Aktivierung erhält der Service Worker Zugriff auf sämtliche ausgehenden Netzwerkanfragen – sowohl auf die eigenen Quelldateien als auch auf externe Anfragen wie an CDNs. Der Service Worker kann im lokalen Zwischenspeicher die Antworten zu den Abfragen hinterlegen.

Abb. 2: Schema des Service WorkersAbb. 2: Schema des Service Workers

Ab diesem Zeitpunkt können die Quelldateien der Anwendung direkt aus dem Cache ausgelesen werden, was sie nicht nur offlinefähig macht, sondern auch noch besonders schnell starten lässt. Der Service-Worker-Updateprozess stellt darüber hinaus sicher, dass neue Versionen der Anwendung schnellstmöglich verfügbar gemacht werden.

Bei Blazor WebAssembly lässt sich die Unterstützung für Progressive Web Apps auf sehr einfache Art aktivieren, wie Abbildung 3 zeigt. Wird das Kontrollkästchen Progressive Web Application beim Anlegen eines neuen Blazor-WebAssembly-Projekts gesetzt, wird dem Projekt automatisch ein passendes Web Application Manifest hinzugefügt und jeweils ein passender Service Worker erzeugt. Im Web App Manifest müssen Anwendungstitel, Icon und Farben angepasst werden. Änderungen am Service-Worker-Skript sind nur dann erforderlich, wenn über die Offlinefähigkeit hinaus weitere Funktionen wie Pushunterstützung implementiert werden sollen.

Abb. 3: Die PWA-Unterstützung beim Anlegen eines neuen Blazor-WebAssembly-ProjektsAbb. 3: Die PWA-Unterstützung beim Anlegen eines neuen Blazor-WebAssembly-Projekts

Pushunterstützung jetzt plattformübergreifend verfügbar

Ähnlich wie plattformspezifische Anwendungen können auch Progressive Web Apps Pushbenachrichtigungen empfangen und Benachrichtigungsbanner darstellen. Hierfür werden drei Webtechnologien kombiniert: das Verfahren Web Push, das Web Notifications API und das Push API [5], die eine Erweiterung der Service-Worker-Schnittstellen ist. Da Service Worker, wie oben erwähnt, auch losgelöst von der eigentlichen Website ausgeführt werden können, ist der Empfang von Pushnachrichten auch dann möglich, wenn die Website gar nicht geöffnet ist.

Was in Chrome, Edge und Firefox schon seit vielen Jahren möglich ist, funktioniert seit Kurzem endlich auch auf der Apple-Plattform: Seit Safari 16 auf macOS Ventura (veröffentlicht im September 2022) können sich Websites für Pushbenachrichtigungen registrieren; auf iOS und iPadOS wurde mit Version 16.4 (veröffentlicht im März 2023) die Unterstützung nachgeliefert. Abbildung 4 zeigt ein Benachrichtigungsbanner am Beispiel einer Demo-PWA auf der Betaversion von iPadOS 16.4. Auf iOS und iPadOS ist zu beachten, dass Pushbenachrichtigungen nur dann empfangen werden können, wenn die Anwendung dem Home-Bildschirm hinzugefügt wurde.

Abb. 4: PWA-Push-Benachrichtigungen unter iPadOS 16.4 Beta 1Abb. 4: PWA-Push-Benachrichtigungen unter iPadOS 16.4 Beta 1

Mächtigeres Web dank Project Fugu

Wie eingangs erwähnt, können Progressive Web Apps lediglich auf die Schnittstellen zurückgreifen, die auf der Webplattform zur Verfügung stehen. Selbst wenn das Web über die vergangenen Jahre stark aufgeholt hat, blieb doch immer der sogenannte „Web App Gap“: eine Lücke zwischen den Möglichkeiten plattformspezifischer Apps und Webanwendungen.

Eine Initiative bestehend aus den Chromium-Beitragenden Google, Intel, Microsoft und weiteren Akteur:innen hat sich zum Ziel gesetzt, diese Lücke weiter zu verkleinern. Als Teil dieses Projekts wurden viele weitere Schnittstellen in das Web eingeführt, etwa für den Zugriff auf die Zwischenablage des Betriebssystems, das Dateisystem oder die Liste installierter Schriftarten.

Alle Schnittstellen werden dabei innerhalb der Web Incubator Community Group (WICG) des W3C diskutiert, gemeinsam mit anderen Browserherstellern und der breiteren Webcommunity. Somit können sie zu jedem Zeitpunkt von anderen Browserherstellern zur Implementierung aufgegriffen werden. Um offizieller Webstandard zu werden, braucht eine Schnittstelle mindestens zwei unabhängige Implementierungen (das sind Apples WebKit, Googles Blink und Mozillas Gecko).

Abb. 5: Der Browser übersetzt die JavaScript-Schnittstellen in die passenden plattformspezifischen AufrufeAbb. 5: Der Browser übersetzt die JavaScript-Schnittstellen in die passenden plattformspezifischen Aufrufe

Abbildung 5 zeigt beispielhaft das Web Share API, eine Schnittstelle, um Inhalte (Texte, URLs oder Dateien) aus einer Webanwendung mit einer anderen, auf dem Betriebssystem installierten Anwendung zu teilen. Das geschieht über die Teilen-Funktion des Betriebssystems. Wenn der Browser die Funktionalität unterstützt, stellt er in JavaScript auf dem navigator-Objekt die Methode share() zur Verfügung – andernfalls gibt es die Methode nicht, was für .NET-Augen ungewöhnlich erscheinen mag. Im Gegensatz zu manch älteren Cross-Plattform-Ansätzen wie Xamarin müssen sich Entwickler:innen nicht selbst darum kümmern, je nach Plattform die korrekte plattformspezifische Schnittstelle aufzurufen. Das fällt in die Zuständigkeit des Browsers: Zu dessen Kompilierungszeit wird die JavaScript-Schnittstelle mit dem passenden plattformspezifischen API verknüpft. Webentwickler:innen rufen nur die eine JavaScript-Methode auf, wenn sie vorhanden ist, egal, auf welcher Plattform.

NuGet-Pakete machen Fugu-Schnittstellen in C# verfügbar

Die allermeisten Webplattform-APIs basieren jedoch auf JavaScript. Zur Verwendung in Blazor und C# muss daher zuerst eine Brücke von C# und WebAssembly zur JavaScript-Welt gebaut werden. Das erfordert fortgeschrittene Kenntnisse beider Welten und kann je nach Schnittstelle sehr aufwendig sein. Aus diesem Grund hat die Blazor-Community Wrapper geschrieben, die in Form quelloffener NuGet-Pakete bezogen werden können. Je nach Schnittstelle wird der Kontakt mit JavaScript dabei entweder komplett vermieden oder zumindest deutlich reduziert. Tabelle 2 zeigt eine Auswahl an Wrapper-Paketen für einige Webschnittstellen aus dem Umfeld von Project Fugu. Im Folgenden werden drei dieser Pakete näher besprochen.

API NuGet-Paket
Async Clipboard API Thinktecture.Blazor.AsyncClipboard
Badging API Thinktecture.Blazor.Badging
File System API KristofferStrube.Blazor.FileSystem
File System Access API KristofferStrube.Blazor.FileSystemAccess
File Handling API Thinktecture.Blazor.FileHandling
Web Share API Thinktecture.Blazor.WebShare

Tabelle 2: Eine Auswahl quelloffener NuGet-Wrapper-Pakete für moderne Webschnittstellen

Progressive Enhancement berücksichtigen

Wie oben beschrieben, sind nicht alle Schnittstellen in jedem Browser und auf jedem Betriebssystem verfügbar. Daher muss zuvor geprüft werden, ob die Schnittstelle auf der Zielplattform auch wirklich nutzbar ist. Der Versuch, eine nicht existente Methode in JavaScript aufzurufen, führt zu einem Fehler. Daher bieten alle oben aufgeführten NuGet-Pakete die Methode IsSupportedAsync() an, mit der sich herausfinden lässt, ob die Schnittstelle auf dem jeweiligen System unterstützt wird (Listing 2).

Listing 2

var isSupported = await badgingService.IsSupportedAsync();
if (isSupported)
{
  // enable badging feature
}
else
{
  // use fallback mechanism or hide/disable feature
}

Steht die Schnittstelle nicht zur Verfügung, gibt es zwei Möglichkeiten: Manchmal steht eine alternative Implementierung bereit, die anstelle der gewünschten Funktion verwendet werden kann. So unterstützt etwa Firefox auf Desktopsystemen das Web Share API nicht. Hier könnte stattdessen das mailto-Pseudoprotokoll genutzt werden. Wird es aufgerufen, öffnet sich der E-Mail-Client. Damit lassen sich Texte dann immerhin aus der Anwendung heraus teilen, wenngleich nicht ganz so komfortabel und umfangreich wie mit dem Web Share API. Gibt es auch keine Fallback-Implementierung, sollte die Funktion ausgegraut oder komplett versteckt werden.

Wichtig ist, dass die Anwendung ihren Dienst auf leistungsschwächeren Systemen nicht komplett quittiert, nur weil eine einzelne Funktionalität nicht verfügbar ist. Genau das beschreibt das Konzept des Progressive Enhancement, das sogar Namensbestandteil des PWA-Modells ist.

 

 

Badging API: Zahlenplaketten für App-Icons

Das Badging API [6] ist eine sehr einfache Schnittstelle, die es Entwickler:innen erlaubt, ein Notification Badge auf dem Icon ihrer Anwendung anzuzeigen. Über diesen Weg können Anwendungen auf unaufdringliche Art und Weise das Vorhandensein von zu erledigenden Aufgaben, ungelesenen Mails oder Instant Messages kommunizieren. Das setzt voraus, dass es auch ein Icon der Anwendung gibt, sie also zuvor installiert wurde.

Nachdem das passende NuGet-Paket installiert wurde (dotnet add package Thinktecture.Blazor.Badging) und der BadgingService in der Program.cs der ServiceCollection hinzugefügt wurde (builder.Services.AddBadgingService()), kann eine Instanz des BadgingService an der gewünschten Stelle angefordert und die Methode SetAppBadgeAsync() mit der gewünschten Zahl aufgerufen werden:

await badgingService.SetAppBadgeAsync(3);

Abbildung 6 zeigt eine installierte Blazor-Demoanwendung im Standalone-Anzeigemodus unter Windows. Auf ihrem Icon in der Taskleiste wird die Windows-spezifische Zahlenplakette mit der Zahl 3 angezeigt.

Abb. 6: Auf dem Icon der installierten Blazor-PWA wird eine Zahlenplakette dargestelltAbb. 6: Auf dem Icon der installierten Blazor-PWA wird eine Zahlenplakette dargestellt

Verfügbar ist die Schnittstelle auf den Chromium-basierenden Browsern unter macOS und Windows sowie auf iOS und iPadOS. Unter Android funktionieren Badges grundsätzlich anders, weswegen das API hier nicht bereitgestellt wird.

File System Access API: Zugriff auf das Dateisystem

Viele Produktivitätsanwendungen wie Büroprogramme, Bild- oder Videobearbeitungsprogramme arbeiten mit einem traditionellen dateibasierten Workflow: Dateien werden eingelesen, bearbeitet und im Dateisystem danach wieder überschrieben. Um diesen Workflow zu ermöglichen, wurde das File System Access API eingeführt. Es erlaubt Entwickler:innenn, ein Handle auf Dateien oder Verzeichnisse anzufordern. Damit können Dateien ausgelesen und überschrieben, aber auch gelöscht und neue Dateien erstellt werden.

Auch hier muss zuvor das passende NuGet-Paket KristofferStrube.Blazor.FileSystemAccess installiert, der Service der ServiceCollection hinzugefügt und die Unterstützung der Schnittstelle auf dem Zielsystem geprüft werden. Listing 3 zeigt, wie das File System Access API aus Blazor WebAssembly heraus angesprochen werden kann: Die Methode ShowOpenFilePickerAsync() auf dem IFileSystemAccessService öffnet einen Dateiauswahldialog. Mit Hilfe der FilePickerOptions kann angegeben werden, welche Dateiformate akzeptiert werden und ob mehr als eine Datei eingelesen werden soll.

Listing 3

try
{
  var fileHandles = await _fileSystemAccessService
    .ShowOpenFilePickerAsync(_filePickerOptions);
  _fileHandle = fileHandles.Single();
}
catch (JSException ex)
{
  Console.WriteLine(ex);
}

Wählen Benutzer:innen im Picker eine Datei aus und bestätigen die Auswahl mit Open, wie in Abbildung 7 gezeigt, teilt der Browser das Datei-Handle mit der Website.

Abb. 7: Auswahl einer Datei über das File System Access APIAbb. 7: Auswahl einer Datei über das File System Access API

Das File System Access API ist derzeit auf Desktopsystemen nur unter Chrome und Edge verfügbar. Apple und Mozilla möchten die Schnittstelle derzeit nicht implementieren. Glücklicherweise gibt es jedoch Fallback-Schnittstellen, um eine Datei vom Dateisystem einzulesen und danach im Downloads-Verzeichnis abzuspeichern. Damit lassen sich manche Anwendungen auch in anderen Browsern umsetzen.

 

 

File Handling API: PWAs als Bearbeitungsprogramm registrieren

Das File Handling API ist eine Erweiterung des File System Access API. Es erlaubt einer PWA, sich bei ihrer Installation als Bearbeitungsprogramm für bestimmte Dateiformate zu registrieren. Auch das ist derzeit nur unter Chrome und Edge auf dem Desktop möglich. Zur Implementierung des API sind zwei Teile erforderlich: Ein deklarativer Teil, bei dem die Unterstützung für bestimmte Dateierweiterungen beim Betriebssystem angemeldet wird, und ein imperativer Teil, bei dem die geöffnete Datei entgegengenommen wird.

Listing 4 zeigt, wie sich die Anwendung bei ihrer Installation als Bearbeitungsprogramm hinterlegen kann. Dazu muss dem Web App Manifest die Eigenschaft file_handlers hinzugefügt werden. Diese Eigenschaft nimmt ein Array entgegen, in dem verschiedene Registrierungen vorgenommen werden können. Jedes Registrierungsobjekt besteht aus einem Dictionary (Eigenschaft accept), das die unterstützten Mediatypen mit ihren jeweiligen Dateiendungen aufzählt. Da auch diese Schnittstelle plattformübergreifend verfügbar ist, müssen beide Angaben hinterlegt werden. Der URL in der Eigenschaft action wird aufgerufen, wenn die PWA mit einer Datei von diesem Format geöffnet wird. Auch ließe sich noch ein Icon hinterlegen, das der Dateiexplorer für Dateien mit dieser Erweiterung darstellen soll.

Listing 4

{
  "file_handlers": [{
    "action": "./",
    "accept": {
      "text/plain": [".txt"]
    }
  }]
}

Wird die Anwendung unter Zuhilfenahme dieses Manifests installiert, registriert sie sich nun als Bearbeitungsprogramm für TXT-Dateien. Abbildung 8 zeigt die Blazor PWA im Öffnen-mit-Menü des Windows Explorers.

Abb. 8: Eine Blazor PWA hat sich als Bearbeitungsprogramm für TXT-Dateien registriertAbb. 8: Eine Blazor PWA hat sich als Bearbeitungsprogramm für TXT-Dateien registriert

Im nächsten Schritt muss der Blazor-Anwendungscode noch angepasst werden, um eine Datei, mit der die PWA als Bearbeitungsprogramm geöffnet wurde, entgegenzunehmen. Auch hierfür muss das passende NuGet-Paket Thinktecture.Blazor.FileHandling installiert, der Service der Collection hinzugefügt und die Unterstützung ermittelt werden. Dann kann mit Hilfe der Methode SetConsumerAsync() ein Launch Consumer gesetzt werden. Dieser Callback nimmt die Startparameter der PWA entgegen. In der Eigenschaft Files findet sich dann die Liste der Handles, mit denen die Anwendung gestartet wurde. Sie entsprechen genau den Handles aus dem File System Access API, die oben demonstriert wurden. Listing 5 zeigt, wie durch die Handles iteriert werden kann und Inhalte aus den Textdateien ausgegeben werden können.

Listing 5

await _fileHandlingService.SetConsumerAsync(async (launchParams) =>
{
  foreach (var fileSystemHandle in launchParams.Files)
  {
    if (fileSystemHandle is FileSystemFileHandle fileSystemFileHandle)
    {
      var file = await fileSystemFileHandle.GetFileAsync();
      var text = await file.TextAsync();
      Console.WriteLine(text);
    }
  }
});

PWAs eignen sich für viele Einsatzgebiete

Progressive Web Apps bieten eine vielversprechende Alternative zu plattformspezifischen Anwendungen: Sie sind schnell und flexibel, sind breit verfügbar auf verschiedenen Endgeräten, einfach zu installieren und zu aktualisieren und können auch offline betrieben werden.

Daher können sie in einer Vielzahl von Anwendungsbereichen eingesetzt werden. Unter anderem lassen sich Produktivitätsanwendungen realisieren, ebenso wie integrierte Entwicklungsumgebungen oder Codeeditoren. Auch Kreativanwendungen wie Bild- oder Videobearbeitungsprogramme können als PWAs implementiert werden, zudem Büroanwendungen wie Textverarbeitungsprogramme, Tabellenkalkulationen oder Präsentationsprogramme. Nicht zuletzt bieten sich PWAs auch für Enterprise-Awendungen, wie z. B. ERP-Systeme oder Kundenportale, an.

Spotify, Visual Studio Code und Photoshop können als Web-App genutzt werden

Dass das Anwendungsmodell marktreif ist, demonstrieren gleich drei sehr bekannte Anwendungen: Spotify hat eine webbasierte Benutzeroberfläche. In den Desktopversionen von Spotify ist diese in einem Electron Wrapper verpackt. Das Spotify PWA unter open.spotify.com sieht dem Desktopclient daher zum Verwechseln ähnlich, sobald man es auf dem System installiert. Als cloudbasierte Anwendung hat es Spotify jedoch relativ leicht, eine Webvariante herauszugeben.

Anspruchsvoller ist da der Code-Editor Visual Studio Code von Microsoft, der auf lokalen Dateien arbeitet. Auch dessen Benutzeroberfläche war schon immer webbasiert. Sein Desktopclient ist mit Electron verpackt, um dem Editor Zugriff auf die plattformspezifischen Schnittstellen zu geben. Mit der Veröffentlichung des File System Access API war es jedoch für Microsoft möglich, Visual Studio Code unter vscode.dev als Webvariante herauszugeben (Abb. 9). Damit können ganze Verzeichnisse geöffnet und bearbeitet werden, auch Plug-ins funktionieren, sofern sie keinen plattformspezifischen Anteil aufweisen. Was jedoch nicht lauffähig ist, ist das Terminal. Denn aus dem Webbrowser heraus gibt es keinen Shellzugriff und es ist unwahrscheinlich, dass er ohne weitere Einschränkungen jemals eingeführt wird. Dennoch lässt sich der Codeeditor damit schnell und unkompliziert öffnen und einfache Anpassungen können vorgenommen werden, ganz ohne ein großes Installationspaket herunterladen zu müssen.

Abb. 9: Visual Studio Code läuft dank des File System Access API direkt im BrowserAbb. 9: Visual Studio Code läuft dank des File System Access API direkt im Browser

Visual Studio Code ist allerdings HTML- und TypeScript-basiert. Etwas näher an Blazor WebAssembly ist die Webvariante von Photoshop, die Adobe im September 2021 veröffentlichte. Die Anwendung setzt ein Creative-Cloud-Abonnement voraus und ist dazu gedacht, kleinere Anpassungen an Bildern vornehmen zu können, ohne gleich den kompletten, sehr umfangreichen Photoshop-Client herunterladen zu müssen.

Photoshop ist eine über Jahrzehnte gewachsene Anwendung. Um in C++ geschriebenen Bestandscode ins Web zu bringen, kooperierte Adobe mit Google, das fehlende Features in WebAssembly und andere fehlende Webschnittstellen implementierte [7]. Und so erhält alter Photoshop-Bestandscode dank WebAssembly ein zweites Leben im Browser. Neu geschriebene Progressive Web Apps reihen sich also in gute Gesellschaft ein.

Abb. 10: Dank Googles Unterstützung brachte Adobe Photoshop ins WebAbb. 10: Dank Googles Unterstützung brachte Adobe Photoshop ins Web

PWAs lösen ihr Versprechen ein

Dank der Progressive Web Apps wird der alte Java-Traum „Write once, run anywhere“ endlich Realität. Über die Jahre ist das Anwendungsmodell immer leistungsfähiger geworden, was die Verfügbarkeit von Pushbenachrichtigungen unter iOS und iPadOS erneut unterstreicht. Dank Initiativen wie Project Fugu ist vorläufig auch kein Ende in Sicht. Außerdem sind Progressive Web Apps gut zugänglich, da sie einfach aus dem Browser heraus aufgerufen werden können.

Blazor WebAssembly wiederum ist interessant für Teams mit bestehendem Wissen in C# und .NET. In C# geschriebene Datenmodelle oder Validierungslogik können zwischen Client und Server geteilt werden und selbst bestehender Code kann gegebenenfalls ins Web übertragen werden.

Einschränkungen des PWA-Modells

Allerdings gibt es auch Einschränkungen im Anwendungsmodell der PWAs: Von Nachteil ist, dass die Installation einer PWA für Anwender:innen möglicherweise nicht offensichtlich ist. Die Installation wird unter iOS und iPadOS über das Teilen-Menü des Browsers ausgeführt, dazu müssen Anwender:innen innerhalb des Menüs auch noch nach unten scrollen. In den Chromium-basierten Browsern wird die Installation in Form einer kleinen Schaltfläche auf der rechten Seite der Adresszeile angeboten.

Darüber hinaus können nur die Schnittstellen genutzt werden, die direkt im Browser verfügbar sind. Bestimmte Anwendungsarten wie Antivirenscanner oder Cloud-Sync-Programme, die einer besonders tiefen plattformspezifischen Integration bedürfen, können nicht als PWA implementiert werden. Schließlich sind nicht alle interessanten APIs auf allen Betriebssystemen und Browsern implementiert, was die Funktionalität einer PWA auf diesen Geräten einschränken kann.

 

ZUM NEWSLETTER

Regelmäßig News zur Konferenz und der .NET-Community

 

Einschränkungen von Blazor WebAssembly

Schließlich weist auch Blazor WebAssembly Einschränkungen auf. Während Entwickler:innen nun vorrangig mit C# arbeiten können, werden sie trotzdem Kenntnisse in HTML, CSS und auch JavaScript benötigen. Darüber hinaus funktioniert die Entwicklungsunterstützung nur in Microsoft Visual Studio auf Windows gut, in Rider wird Blazor bisher nur stiefmütterlich unterstützt.

Das wohl größte Problem von Blazor WebAssembly ist allerdings die umfangreiche Bundle-Größe der Anwendung. Eine Hello-World-Anwendung wird schon im Minimalfall (z. B. durch Entfernung der Kulturinformationen) rund 2 MByte groß – ein Vielfaches, verglichen mit den 50 KByte einer einfachen Angular-Anwendung. Da wird auch die Ahead-of-Time-Kompilierung (AoT) keine Abhilfe schaffen; hier werden die Apps tendenziell sogar noch größer. Die Bundle-Größe führt daher zu einem Nachteil in der initialen Ladezeit, insbesondere bei Nutzung von weniger schnellen Verbindungen, etwa bei mobilen Anwendungen.

Um dieses Problem abzumildern, setzt Blazor ein recht aggressives Caching ein. Das kann allerdings zur Entwicklungszeit zu einiger Verwirrung führen, wenn im Browser eine veraltete Version angezeigt wird.

Des Weiteren werden bei Blazor WebAssembly DLL-Dateien zum Browser übertragen. Da es sich dabei um ausführbare Dateien handelt, können Unternehmensproxys und -firewalls einen Strich durch die Rechnung machen, sodass die Blazor-Anwendung gar nicht erst startet. Mit dem WebCIL-Format ist hier jedoch bereits eine Lösung in Sicht.

Zusammengefasst ist Blazor WebAssembly für B2C-Anwendungen oder andere Umgebungen, die nicht kontrolliert werden können, möglicherweise nicht die beste Wahl.

Zusammenfassung

Blazor, Progressive Web Apps und Project Fugu sind großartige Technologien, um Webanwendungen zu entwickeln: Blazor WebAssembly ermöglicht es Entwickler:innen, ihre bestehenden C#- und .NET-Kenntnisse zu nutzen, um Apps zu entwickeln, die nicht nur auf allen relevanten Browsern laufen, sondern auch ohne Installation direkt im Browser. Progressive Web Apps verbessern das Nutzungserlebnis von Webanwendungen durch Offlinefähigkeit und Installierbarkeit. Project Fugu bringt auch weiterhin neue Schnittstellen ins Web, um eine noch tiefere Integration mit dem Betriebssystem zu erreichen. C#-basierte NuGet-Pakete aus der Community erleichtern die Verwendung dieser Schnittstellen. Zu guter Letzt sollte immer an das Konzept des Progressive Enhancement gedacht werden, um sicherzustellen, dass Anwender:innen älterer oder weniger leistungsfähiger Browser die App weiterhin benutzen können. Wenn Sie all diese Konzepte berücksichtigen, schreiben Sie großartige Webanwendungen genau einmal und bringen Sie zu all Ihren Anwender:innen, ganz egal, welche Plattform sie nutzen.

Ihr aktueller Zugang zur .NET- und Microsoft-Welt.
Der BASTA! Newsletter:

Behind the Tracks

.NET Framework & C#
Visual Studio, .NET, Git, C# & mehr

Agile & DevOps
Agile Methoden, wie Scrum oder Kanban und Tools wie Visual Studio, Azure DevOps usw.

Web Development
Alle Wege führen ins Web

Data Access & Storage
Alles rund um´s Thema Data

JavaScript
Leichtegewichtig entwickeln

UI Technology
Alles rund um UI- und UX-Aspekte

Microservices & APIs
Services, die sich über APIs via REST und JavaScript nutzen lassen

Security
Tools und Methoden für sicherere Applikationen

Cloud & Azure
Cloud-basierte & Native Apps