Zukunft der Webentwicklung: Webkomponenten und Progressive Web Apps, Teil 2

Bei Progressive Web Apps handelt es sich um Webanwendungen, die sich ähnlich wie ihre nativen Gegenstücke anfühlen. Davon kann insbesondere die App-Programmierung profitieren.

In Pocket speichern vorlesen Druckansicht
Zukunft der Webentwicklung: Webkomponenten und Progressive Web Apps, Teil 2
Lesezeit: 10 Min.
Von
  • Stefan Neumann
Inhaltsverzeichnis

Wer mit seiner App auf Smartphones präsent sein möchte, hat viele Möglichkeiten zur Umsetzung. Die einfachste ist sicherlich, die App als "Internetseite" ins Netz zu stellen. Hier sind nur Browserunterschiede zu beachten, und es gibt keine Probleme mit Updates. Solche Web-Apps sind zwar von vielen Smartphone-Funktionen abgeschnitten, diese werden aber nicht immer benötigt. Nun finden sich in den App-Stores aber viele Angebote, die auch als Web-App funktionieren würden. Warum das so ist und wie die sogenannten Progressive Web Apps hier Abhilfe schaffen sollen, ist Thema dieses Artikels.

Mehr Infos

Ein zentraler Vortrag zu den im Folgenden vorgestellten Progressive Web Apps lässt keinen Zweifel daran, dass Google mit der Verbreitung von Web-Apps auf mobilen Geräten unzufrieden ist.

Die Protagonisten meinen auch zu wissen, was dafür verantwortlich ist: Zum einen seien Webanwendungen nicht "app-like" genug. Man kann sie nicht vom Homescreen aus starten, und sie können keine Benachrichtigungen anzeigen, wenn sie nicht explizit gestartet wurden. Zum anderen funktionieren sie nicht mehr, wenn man offline ist. Seit Anfang 2015 beherrscht Chrome Techniken, mit denen Google gegensteuern möchte. Ein Jahr später zog Firefox nach, bei Microsoft ist die Sache wohl in Arbeit. Ein Mitte 2015 von Googles Mitarbeiter Alex Russel veröffentlichter Blogbeitrag hat diesen Techniken einen Stempel aufgedrückt: Progressive Web Apps (PWA).

Der Begriff erinnert an "Progressive Enhancement", also die Fähigkeit einer Webseite, Möglichkeiten des Browsers zu nutzen, ohne auf sie angewiesen zu sein. PWA überträgt das auf die Fähigkeit einer Web-App, stufenweise zur nativen App zu mutieren – oder präziser: Vom Standpunkt des Nutzers aus verhält sie sich wie eine native App. Mit Anwendungen, die über App Stores vertrieben werden, hat das nichts zu tun, auch wenn diese mit dem Web-Stack (HTML, CSS, JavaScript) erstellt wurden. Es geht um simple Internet-Adressen. Die Seiten beziehungsweise Anwendungen, die darüber aufgerufen werden, sind ganz normal nutzbar. Dass sie mehr können, fällt Anwendern erst auf, wenn sie eine PWA-fähige Umgebung verwenden. Ohne Verschlüsselung (https) kommt man hier allerdings nicht weit. Nur während der Entwicklung ist ein Laden von "http://localhost" möglich.

Im Wesentlichen sind es nur zwei Techniken, die eine Web-App "progressiv" machen. Manifest-Dateien und Service Worker. Chrome erkennt häufiger benutzte Seiten und bietet an, sie auf dem Homescreen abzulegen (man kann das aber auch selbst direkt vornehmen). Seit Chrome 47 wird beim Start der Anwendung auch ein Splash-Screen angezeigt. Dazu benötigt der Browser bestimmte Daten: den Namen der App, ein Icon, den Namen der Datei, die die App lädt, die Hintergrundfarbe für den Splash-Screen et cetera. Das wird über die Mainfest-Datei zur Verfügung gestellt. Wie kaum anders zu erwarten, ist sie in JSON notiert.

Das hilft aber lediglich, eine Internet-Anwendung auf den Homescreen zu bringen, den Rest des "Jobs" erledigen Service Worker. Vereinfacht könnte man sagen, dass ein Service Worker der App vorgaukeln kann online zu sein, selbst wenn sie tatsächlich offline ist.

Service Worker klingt nach dem länger nutzbaren Web Worker, tatsächlich ist das dahinter stehende Verfahren ähnlich. In beiden Fällen wird eine separate JavaScript-Datei geladen, deren Code parallel ausgeführt wird. Es gibt keinen Zugriff auf das DOM, stattdessen wird über Events mit der eigentlichen App kommuniziert. Da enden dann aber die Gemeinsamkeiten, denn Service Worker dienen einem völlig anderen Zweck: Man erhält die Kontrolle über die Datei- und Datenbeschaffung. Dem Browser wird mitgeteilt, welche Anfragen nicht ins Netz gehen, sondern vom eigenen JavaScript-Code verarbeitet werden. Ab dem zweiten Start der WebApp, fällt dort die Entscheidung, ob der Server die Daten neu abholt oder ob man zwischengespeicherte Daten verwendet. Service Worker kollidieren daher mit einer weiteren, etwas älteren Technik – dem AppCache. Er wird selten genutzt, da die Spezifikation recht lang geraten ist und sich der Browser "gefühlt" unvorhersehbar verhält.

Man könnte Service Worker durchaus als programmierbaren AppCache bezeichnen. Einfache Dinge sind mit der älteren API sicherlich schneller umgesetzt, dafür stößt man beim Service Worker nicht so schnell an die Grenzen des Machbaren. Immerhin hat man es mit einer Art clientseitigen Netzwerk-Proxy zu tun. So kann man im Service Worker sogar auf langsame Verbindungen reagieren und dem Anwender erst einmal die gecachten Inhalte präsentieren. Der AppCache kennt hier nur on- oder offline.

Eine Einschränkung von "Workern" an sich betrifft auch den Service Worker: Er arbeitet streng asynchron. So lässt sich LocalStorage nicht als Cache nutzen, IndexedDB hingegen schon. Es kommen die seit ECMAScript 6 zum Sprachumfang von JavaScript gehörernden Promises zum Einsatz. Sie sollen die Arbeit mit asynchronen Abläufen erleichtern, sind aber selbst für langjährige JavaScript-Programmierer nicht auf Anhieb verständlich. Die Verwendung von Promises geht schon bei der Installation des Workers los, das folgende Beispiel setzt aber einen Schritt später an.

Im Browser hängen globale Variablen an window. Da Worker fensterlos in ihrem eigenen Thread ausgeführt werden, übernimmt diese Rolle self. Hier gibt es unter anderem das caches-Objekt (Cache Storage API), das wiederum mehrere benannte Cache-Objekte verwalten kann. Während der Installation geben Entwickler einem solchen Objekt dann mit, welche Dateien es cachen soll. Der folgende Code greift auf gecachte Dateien zurück. Das fetch-Ereignis tritt ein, wenn der Browser ins Netz will.

self.addEventListener('fetch', onFetch);

function onFetch(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
if (response) {
return response;
}
return fetch(event.request);
}
)
)
}

Das Fetch-Event hat eine respondWith-Methode, der die Funktion übergeben wird, die auf die Anfrage reagiert. Hier wird das ebenfalls am Event hängende Request-Objekt der match-Methode vom CacheStorage übergeben und die match-Methode jedes Cache-Objekts aufgerufen, bis das passende gefunden wurde. Die Methode gibt nur einen Promise zurück. Über dessen then-Methode können Entwickler auf das eigentliche Ergebnis von match() reagieren. War die Suche erfolgreich, bricht die Funktion mit der Rückgabe eines Response-Objekts ab, ansonsten wird das Request-Objekt benutzt, um die Datei aus dem Netz zu holen. Der Service Worker stellt hierzu fetch() zur Verfügung. Dieser Code stellt im Grunde das Minimum dar, um den AppCache zu ersetzen. Es kann durchaus eine Weile dauern, bis man sich in die diversen beteiligten APIs hineingedacht hat.

Für viele vermutlich überraschend: Der Service Worker überlebt das Schließen der App (respektive des Tabs), auf Android sogar das (scheinbare) Schließen von Chrome. Wie lange der JavaScript-Code eines Service Workers aktiv bleibt, hängt von Chromes "Laune" ab. Tut sich zu lange nichts, wird der Speicher freigegeben. Nutzt man die App hingegen wieder, wird auch der Service Worker wieder zum Leben erweckt. Das bedeutet leider auch, dass auf globale Variablen kein Verlass ist.

Das Verhalten ist aber notwendig, um eine der oben genannten Anforderung zu erfüllen: Benachrichtigungen anzeigen, auch wenn die Web-App gar nicht geöffnet ist. Das wird über Push Notifications erreicht, auf die Entwickler über einen Service Worker zugreifen können. Nicht nur das Starten der App, auch das Eintreffen einer solchen Nachricht aktiviert den Service Worker wieder. Auf dem Desktop funktioniert das nur, solange Chrome tatsächlich geöffnet ist, iOS ist hier komplett außen vor.

Googles Chrome-Team betreibt im Rahmen seiner PWA-Strategie die Standardisierung dreier weiterer APIs, die vor allem das mobile Einkaufen erheblich erleichtern sollen. Unter Marketing-Experten hat sich längst herumgesprochen, dass Kunden einen Artikel eher selten mit dem Smartphone bestellen, selbst wenn sie ihn dort ausgesucht haben. Das Anmelden bei Shops, bei dem sie bereits Kunde sind, und der Checkout bei einer Erstbestellung nerven meistens schon genug, wenn sie vor einer richtigen Tastatur sitzen. Mobil tut man sich das ungern an.

Die Credential Management API will den Log-in-Prozess automatisieren. Hier ist die Herausforderung, wie Daten gespeichert und übertragen werden, ohne dass Identitätsdiebstahl möglich ist. Auch an das Anmelden über dritte Parteien wie Facebook hat man gedacht (federated login). Ebenso sicherheitskritisch ist die "Payment Request API", die den Check-out auf ein oder zwei Taps reduzieren soll. Das umständliche Ausfüllen von Formularen wird komplett abgeschafft. Als Drittes strebt man noch die Einbindung von Geräten an, die über Blootooth Low Energy funken. Das macht insofern Sinn, als dass sich auf dem Smartphone eintreffende Informationen an andere Geräte weiterreichen lassen oder Web-Apps genügen, um diese zu steuern.

Ein nigerianisches Start-up-Unternehmen, das mit Amazon konkurrieren will, ist bei der Nutzung von diesen noch relativ neuen Techniken vorgeprescht. Nutzer wurden eingeladen, die Beta-Version von konga.com zu testen, die als PWA mit Polymer umgesetzt wurde. In Nigeria ist surfen ein teurer Spaß. Käufer erwägen nicht nur den Preis der Ware selbst, sondern auch, was es sie kostet, sich auf den Seiten des Shops zu bewegen. Durch extreme Reduzierung und passgenaue Bildgrößen ließen sich die Downloadgrößen drastisch reduzieren. Das mit Polymer umsetzbare Lazy Loading und die Möglichkeit, das Caching mit einem Service Worker zu optimieren, waren hier sicherlich hilfreich.

Wie man sieht, wird Google nicht müde, andere Browserentwickler und Standardisierungsgremien vor sich her zu treiben. Schon eine Manifest-Datei genügt, um vielen Nutzern ein besseres mobiles "Erlebnis" zu verschaffen. Auch in Service Worker Zeit zu investieren, dürfte sich lohnen. Denn im umtriebigen Smartphone-Business steigt die Zahl der Nutzer, die davon profvitieren, von Woche zu Woche.

Stefan Neumann
ist Webentwickler der ersten Stunde und betreut bei der tma pure GmbH das hausinterne Shop-System. Für die Planung eines Open-Source-CMS werden von ihm die neusten Web-App-Trends genauer betrachtet.
(ane)