Über unsMediaKontaktImpressum
Christian Liebel 26. März 2019

Progressive-Web-Apps: Echte Cross-Platform-Apps mit Angular

Früher war die Anwendungsentwicklung noch einfach: Ein Windows-Client war völlig ausreichend und deckte die komplette Nutzerbasis ab. Doch die Plattformhegemonie ist längst vorbei. Mobilplattformen wie iOS und Android sind heute mindestens genauso relevant wie Windows auf dem Desktop. Doch auch dort machen sich Systeme wie macOS oder Chrome OS zunehmend breit. Wäre es nicht schön, auch heute eine Anwendung zu entwickeln, die auf allen relevanten Mobil- und Desktop-Plattformen sowie als Bonus noch im Webbrowser funktioniert? Mithilfe der Progressive-Web-Apps und dem Framework Angular wird genau das möglich.

Angular: Webanwendungen leicht gemacht

Angular [1] ist ein beliebtes Framework zur Umsetzung von Single-Page-Web-Applications (SPA) auf Basis von HTML, JavaScript und CSS. Unter einer SPA versteht man einen Typ Webanwendung, der als Fat Client realisiert ist. Für einen Sichtwechsel wird insbesondere kein serverseitiger Roundtrip erforderlich, wie dies bei JavaServer Faces oder ASP.NET Core MVC der Fall wäre. Diese Anwendungen fühlen sich somit genauso schnell an wie native Anwendungen.

Das quelloffene, kostenfrei verwendbare Framework wird von Google entwickelt und wurde aus Erfahrungen abgeleitet, die das Unternehmen bei der Entwicklung großer Webanwendungen wie Google Mail oder Maps gemacht hat. Angular hat einen üppigen Lieferumfang und konkrete Architekturvorstellungen. Entwickler müssen sich also nicht erst Gedanken über die Infrastruktur machen, sondern können direkt mit der Implementierung ihrer Anwendung loslegen. Auch für das Aufsetzen eines neuen Angular-Projektes gibt es Unterstützung: Angular bietet ein Kommandozeilentool namens Angular CLI [2] an, das über den Node.js Package Manager (npm) installiert werden kann. npm ist ein gängiges Werkzeug in der Welt der Webentwicklung und setzt eine Node.js-Installation voraus. Durch den Aufruf des folgenden Kommandos wird die Angular CLI installiert:

npm i -g @angular/cli

Danach steht auf der Kommandozeile der Befehl ng (von Angular) zur Verfügung. Mithilfe des Befehls ng new wird ein komplett neues Angular-Projekt angelegt. Die Angular CLI legt dabei die komplette Ordnerstruktur sowie ein Repository für die Versionsverwaltung Git an und installiert alle Paketabhängigkeiten. Ein neues Projekt mit dem Namen "myApp" würde also wie folgt erzeugt:

ng new myApp

Bei der Ausführung dieses Kommandos wird zugleich abgefragt, ob die Anwendung einen clientseitigen Sichtwechsel (Routing) unterstützen soll und welches Stylesheetformat gewünscht wird.

Außerdem enthält die Angular CLI einen Buildprozess, um die implementierte Anwendung in der kleinstmöglichen Form auf einem Server bereitzustellen, einen Entwicklungsserver, um den Entwicklungsstand komfortabel anzusehen (einschließlich automatischer Aktualisierung bei Änderung von Programmcode) und unterstützt sowohl Unit- als auch End-to-end-Tests – eben alles, was man für Enterprise-ready Anwendungsentwicklung benötigt. Was bei der Projektstruktur beginnt, setzt sich bei den Architekturmitteln fort. Angular folgt dem MV*-Entwurfsmuster und entkoppelt das Datenmodell von der View (HTML) und der Logik in JavaScript bzw. TypeScript. Werte können per Data-Binding an die Oberfläche gebunden und bei Änderung automatisch aktualisiert werden – wie es etwa bei der Windows Presentation Foundation (WPF) gehandhabt wird. Unter anderem definiert das Framework folgende Architekturmittel:

Baustein Zweck
Komponente Wiederverwendbarer, UI-bezogener Baustein mit eigenem HTML-Template
Direktive Wiederverwendbarer, UI-bezogener Baustein zur Modifikation von Verhalten oder Aussehen von DOM-Knoten oder Angular-Komponenten
Pipe Wiederverwendbarer, UI-bezogener Baustein zur Modifikation der Anzeige gebundener Daten
Service Wiederverwendbarer, nicht-UI-bezogener Baustein zur Kapselung von Infrastruktur- oder Domänenlogik
Modul Wiederverwendbare Sammlung von Komponenten, Direktiven, Pipes, Services und mehr

Die Angular CLI kann diese Bausteine komfortabel anlegen. Eine neue Komponente namens "list" ließe sich über das folgende Kommando anlegen (dazu zunächst in den Angular-Projektordner navigieren, im Beispiel von oben müsste also zuerst cd myApp durchgeführt werden):

ng generate component list

Im Ergebnis werden durch die Ausführung dieses Kommandos vier Dateien generiert:

  • list.component.html: Enthält das HTML-Template (View)
  • list.component.ts: Logikklasse, z. B. zum Bezug von Daten, in TypeScript
  • list.component.css: CSS-Stylesheet zum Stylen des HTML-Templates
  • list.component.spec.ts: Skelett für Unit-Tests

Es gibt bei Angular also eine klare Aufgabenteilung, sodass sich Designer etwa rein um das CSS kümmern können, während der Anwendungsentwickler die passende Logik schreibt.

Listing 1: TypeScript-Logikklasse einer Angular-Komponente

import { Component } from '@angular/core';

@Component({
  selector: 'app-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.css']
})
export class ListComponent {
  title = 'Liste';
}

Listing 2: HTML einer Angular-Komponente. Die geschwungenen Klammern werden zur Laufzeit an das gleichnamige Feld der Komponentenklasse gebunden

<h1>
  {{ title }}
</h1>

Ein häufiger Kritikpunkt in der Webentwicklung ist die Verwendung von JavaScript als Sprache. JavaScript funktioniert trotz des ähnlichen Namens grundsätzlich anders als Java oder andere im Desktop- und Mobile-Umfeld verwendeten Programmiersprachen wie C# oder C++. Insbesondere ist die Sprache schwach und dynamisch typisiert. Das erlaubt zwar eine hohe Flexibilität, öffnet zeitgleich aber die Tür für schwer zu reproduzierende Bugs. Um dieses Problem zu adressieren, entwickelte Microsoft die Sprache TypeScript, die eine Übermenge von JavaScript darstellt: Jeder gültige JavaScript-Codeschnipsel ist zugleich in TypeScript gültig. Im Gegensatz zu JavaScript unterstützt TypeScript aber statische Typisierung. Somit kann der Entwickler beim Schreiben eine Codevervollständigung nach dem Vorbild IntelliSense erhalten. Außerdem prüft TypeScript, ob zugegriffene Eigenschaften überhaupt vorhanden sind und ob diese im korrekten Datentyp vorliegen. TypeScript wird von Anders Hejlsberg entworfen, der auch für C# verantwortlich zeichnet. Ebenso kennt JavaScript bislang noch keine Zugriffsmodifizierer wie public oder private. Auch hierfür liefert TypeScript die passende Unterstützung nach, wie auch für aus anderen Programmiersprachen bekannte Interfaces. Allerdings kann TypeScript nicht von gängigen Webbrowsern interpretiert werden und muss vor Auslieferung daher wieder nach JavaScript kompiliert werden. Diesen Vorgang nennt man auch Transpilierung und wird durch die Angular CLI wieder automatisch vorgenommen:

ng build

Durch die Ausführung dieses Kommandos werden unter anderem TypeScript-Dateien transpiliert und sämtliche Quelldateien der Angular-App in wenige Dateien gebündelt, sodass die Anwendung leichter bereitzustellen ist. Werden die Quelldateien einer Single-Page-App einmal geladen, ist nur noch zum Bezug oder zur Modifikation extern gespeicherter Daten eine Internetverbindung erforderlich. Das bedeutet auch, dass die Anwendung offline funktioniert – zumindest bis zum nächsten Reload.

Progressive-Web-Apps: 10 Eigenschaften führen zum Glück

Genau hier setzen Progressive-Web-Apps an: ein vielversprechendes Anwendungsmodell, wieder aus dem Hause Google. Dieses Modell möchte Webanwendungen, etwa mit Angular geschrieben, auf eine Stufe mit nativen Anwendungen heben: Das schließt eine dauerhafte Offlinefähigkeit (nicht nur bis zum nächsten Reload), ein eigenes Symbol auf dem Homebildschirm (Mobile) oder der Programmliste (Desktop), die native Darstellung in einem eigenen Fenster (Desktop) beziehungsweise vollflächig (Mobile) sowie Pushbenachrichtigungen mit ein. Progressive-Web-Apps sind allerdings keine klar umrissene Technologie, sondern eine Sammlung von Eigenschaften, die eine solche Webanwendung erfüllen soll beziehungsweise muss. Typischerweise werden dabei die folgenden zehn Eigenschaften genannt [3]:

  1. Connectivity-independent: Progressive-Web-Apps funktionieren auch offline oder mit schlechter Internetverbindung.
  2. Fresh: Trotz Offlinekopie erhält der Anwender möglichst zügig neue Versionen der PWA.
  3. Installable: Eine PWA kann auf dem Homebildschirm beziehungsweise der Programmliste installiert werden.
  4. Reengageable: Können den Anwender durch Pushbenachrichtigungen zum erneuten Verwenden der App bewegen.
  5. Discoverable: PWA können von normalen Websites unterschieden werden.
  6. App-like: Setzen von nativen Apps bekannte Navigationsstrukturen um und verhalten sich, wie man es von nativen Apps gewöhnt ist.
  7. Safe: Werden über eine verschlüsselte Verbindung ausgeliefert.
  8. Progressive: PWA schließen Nutzer älterer Webbrowser nicht aus, aber bieten Anwendern mit moderneren Webbrowsern Zusatzfeatures.
  9. Linkable: Auf die Anwendung und Zielzustände kann per URL verwiesen werden.
  10. Responsive: Funktionieren auf unterschiedlichsten Bildschirmabmessungen vom Smartphone bis zum 42-Zoll-Fernseher.

Zentrale technische Mittel zur Umsetzung einer PWA sind der Service Worker samt Cache API zur Umsetzung von Offlinefähigkeit sowie das Web-App-Manifest zur Darstellung der Anwendung in einer nativen Form.

Wie per Einzeiler die Angular-App zur PWA wird

Angular enthält von Haus aus eine Unterstützung für Progressive-Web-Apps, die auf Wunsch installiert werden kann. Der Entwickler muss sich dabei nicht zwangsläufig schon zum Projektstart dafür entscheiden, sondern kann die Unterstützung auch nachträglich installieren. Auch die Installation der PWA-Unterstützung erfolgt über die Angular CLI als Einzeiler:

ng add @angular/pwa

Durch die Ausführung dieses Kommandos werden dem Projekt verschiedene Dateien und Abhängigkeiten hinzugefügt. Außerdem werden Änderungen an den Angular-Projektdateien vorgenommen, um die PWA-Unterstützung zu aktivieren.

Web-App-Manifest: App-Aussehen definieren

Eine der hinzugefügten Dateien ist das Web-App-Manifest (manifest.json). Diese Datei definiert das Aussehen der installierten Anwendung, also ihren Titel, Theme-Farben oder die Symbole zur Darstellung auf dem Homebildschirm oder in der Programmliste. Passende Symbole hat die Angular CLI dem Projekt automatisch zum Ordner src/assets/icons hinzugefügt. Diese zeigen das Angular-Logo. Die Symboldateien können nach Belieben angepasst werden.

Ist ein Web-App-Manifest vorhanden, dient dies darüber hinaus Suchmaschinenanbietern oder App-Store-Betreibern als Hinweis, dass es sich bei diesem Webangebot nicht um eine reguläre Website handelt, sondern um eine Web-App.

Damit Webbrowser die Anwendung zur Installation anbieten, müssen aber noch weitere Kriterien erfüllt sein. Insbesondere regelt das Web-App-Manifest nicht, wie die Quelldateien der Angular-Anwendung offline gehalten werden. Das muss aber unbedingt möglich sein, bevor die App ein Symbol auf dem Homebildschirm oder in der Programmliste erhalten kann. Dazu kommt eine zweite Technologie ins Spiel: Der Service Worker.

Service Worker: Kontrolle über offline und online

Der Service Worker ist ein Stück JavaScript, das von der Website registriert werden kann. Einmal registriert, übernimmt der Service Worker die Kontrolle über die Website: Er agiert als Controller, Proxy beziehungsweise Interceptor. Gemeinsam mit dem Service Worker hat auch die Cache API Einzug in die Webbrowser erhalten. Dieser Cache darf nicht mit dem normalen HTTP-Browsercache verwechselt werden, der in unveränderter Form weiterbesteht. Im Zwischenspeicher der Cache API können HTTP(S)-Anfragen und ihre zugehörigen Antworten hinterlegt werden. Der Service Worker kann an zentraler Stelle entscheiden, ob HTTP(S)-Anfragen der Website über das Netzwerk bedient werden sollen oder aus dem Cache. Somit wird die Offlinefähigkeit der Anwendungsquelldateien umgesetzt: Bei der Installation werden die Quelldateien im Cache hinterlegt und künftig von dort ausgeliefert. Das macht die Anwendung nicht nur offlinefähig, sondern auch noch sehr schnell, da die Dateien künftig nicht mehr über das Internet geladen werden müssen.

Das Aufsetzen eines Service-Worker-Skriptes kann allerdings recht kompliziert werden. Daher nimmt die Angular CLI dem Entwickler diesen Schritt komplett ab. Das Angular-Team stellt mit dem Angular Service Worker (NGSW) eine "One-size-fits-all-Service-Worker-Implementierung" bereit. Diese Implementierung übernimmt das Caching der Angular-Quelldateien. Auf Wunsch können auch Pushbenachrichtigungen (über den Angular-Service SwPush) und das Caching externer Daten aktiviert werden (über die Datei src/ngsw-config.json). Der Service Worker wird jedoch nur produktiven Builds der Angular-Anwendung hinzugefügt. Diese werden wie folgt ausgeführt:

ng build --prod

Um den Build auszuprobieren, muss dieser durch einen HTTP-Server ausgeliefert werden, zum Beispiel so:

cd dist/myPwa
npx lite-server

Danach öffnet sich die mit dem Service Worker versehene Angular-App in einem neuen Browserfenster. Da die Anwendung somit nun offline ausgeführt werden kann, sind auch die Bedingungen zur Installation der Angular-App erfüllt.

PWA installieren

Die Installation wird je nach Browser entweder automatisch vorgeschlagen, kann aber auch aus der Webanwendung heraus ausgelöst oder manuell durchgeführt werden. Unter Google Chrome wird die manuelle Installation über das Drei-Punkte-Menü vorgenommen. Installation meint hier übrigens das reine Hinzufügen eines Symbols auf dem Homebildschirm oder in der Programmliste. Die Offlinefähigkeit der Anwendung funktioniert bereits in der Browserregisterkarte – wie auch die Pushbenachrichtigungen. Vom Homebildschirm oder der Programmliste geöffnet kann die Anwendung aber in einem eigenen Fenster beziehungsweise auf Mobilgeräten vollflächig ausgeführt werden. Insbesondere erscheint die App auch im App-Switcher des Betriebssystems.

Offline orthogonal zu Service Worker

Der Cache des Service Workers eignet sich lediglich zum Ablegen von HTTP(S)-Anfragen und dazu passenden Antworten. Anwendungen basieren in den meisten Fällen aber nicht nur auf statischen Quelldateien, sondern verarbeiten (strukturierte) Daten. Doch auch dafür ist das Web gerüstet. Mithilfe der Indexed Database (IndexedDB) steht eine Browserdatenbank zur Verfügung, auf die sowohl Service Worker als auch Webanwendung Zugriff haben. Speichert die Webanwendung grundsätzlich nur in die IndexedDB, bleibt sie offlinefähig. Von dort wird dann allerdings eine Synchronisationslogik benötigt, welche den lokalen Datenstand mit einem entfernten Server austauschen kann. Wo es zwei Datenstände gibt, können überdies Konflikte auftreten. Dies muss bei der Implementierung offlinefähiger Weblösungen von vornherein bedacht werden.

Zu viel Magie? Alternativen zum Angular Service Worker

Die PWA-Unterstützung von Angular lässt sich sehr einfach installieren und betreiben. Allerdings geht dies zu Lasten der Flexibilität. Für die meisten Fälle mag der Funktionsumfang des Angular Service Workers genügen. Service Worker können allerdings auch Daten im Hintergrund synchronisieren, wenn diese gar nicht geöffnet ist oder Dateien im Hintergrund herunterladen. Der Angular Service Worker stellt diese Schnittstellen derzeit noch nicht bereit.

Es gibt jedoch auch eine Alternative, ohne das Service-Worker-Skript komplett selbst zu schreiben. Mithilfe des Google-Toolkits Workbox[4] können etwa die Quelldateien automatisiert gecacht werden, während andere Teile des Service-Worker-Skripts selbst ausimplementiert werden. Allerdings entfällt bei diesem Ansatz die Angular-CLI-Integration.

Fazit

Progressive-Web-Apps haben das Potenzial, die Anwendungsentwicklung grundlegend zu verändern. Das Anwendungsmodell funktioniert plattformübergreifend: Mit einer einzigen Codebasis können Anwendungen für den Browser, Mobilgeräte sowie den Desktop geschrieben werden. Dank eines SPA-Frameworks wie Angular müssen Entwickler auch nicht auf Architekturmittel verzichten, die sie auch anderen Programmierumgebungen gewohnt sind. Mit Twitter oder Telegram sind die ersten größeren PWAs bereits in Betrieb und zunehmend mehr Entwickler springen auf den Zug auf.

Wenn Sie Interesse an diesem Thema gefunden haben, möchte ich Ihnen mein Praxisbuch zu Progressive-Web-Apps ans Herz legen. Dort beschreibe ich das PWA-Anwendungsmodell im Detail, einschließlich weiterführender Informationen zu den Technologien Web-App-Manifest, Service Worker und Cache API. Neben einem durchgängigen Tutorial zur Angular-Unterstützung für PWAs führe ich auch das Toolkit Workbox näher aus und beschreibe, wie Sie für Ihre PWA ein natives Look-and-feel erreichen, Bestandsanwendungen migrieren und auch in der Zeit nach dem App-Store Zahlungen mit Ihrem Benutzer abrechnen können.

Autor

Christian Liebel

Christian Liebel setzt moderne Businessanwendungen auf Basis von Angular und .NET Core um. Für seine Communityaktivitäten wurde er als Google Developer Expert (GDE) und Microsoft Most Valuable Professional (MVP) ausgezeichnet.
>> Weiterlesen
Buch des Autors:

Das könnte Sie auch interessieren
botMessage_toctoc_comments_9210