Hintergrund-Synchronisation für PWAs, Teil 1: Background Sync API

In dieser Serie geht es um die Synchorisation von Daten zwischen PWA und Anwendungsserver im Hintergrund. Den Anfang macht die Background Sync API, die seit 2016 in Chrome funktioniert.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 5 Min.
Von
  • Christian Liebel

In dieser Reihe geht es um die Möglichkeit, im Hintergrund Daten zwischen einer Progressive Web App und dem Anwendungsserver auszutauschen – auch dann, wenn die Anwendung gar nicht geöffnet ist. Den Anfang macht die Web Background Synchronization API, die in auf Chromium basierenden Browsern schon seit 2016 funktioniert.

Progressive Web Apps laufen dank dem Service Worker und der IndexedDB offline: Im Cache des Service Worker können die Quelldateien der Anwendung offline gehalten werden, in der lokalen Clientdatenbank die strukturierten Anwenderdaten. Die Background Sync API möchte Progressive Web Apps nun um die Funktionalität ausstatten, Daten auch im Hintergrund mit dem Anwendungsserver auszutauschen. Das Verhalten ist von nativen Anwendungen wie WhatsApp bekannt: Anwender können eine Nachricht verfassen, absenden und das Smartphone wieder wegpacken. Besteht eine Internetverbindung, wird die Nachricht direkt verschickt. Andernfalls wird sie im Hintergrund übermittelt, sobald wieder eine Verbindung zur Verfügung steht. Die App muss dafür nicht noch einmal geöffnet, das Smartphone nicht noch einmal aus der Hosentasche gekramt werden.

Bei der Background Sync API handelt es sich um eine Erweiterung der Service-Worker-Schnittstellen, eine der technischen Grundlagen von Progressive Web Apps. Ein Service Worker ist ein Stück JavaScript, das von der Website registriert wird. Das Skript kann anschließend losgelöst von der ursprünglichen Website laufen – also auch dann, wenn die Website gar nicht geöffnet ist. Genau diese Eigenschaft macht man sich bei der Background Sync API zunutze.

Da nicht jeder Browser mit Unterstützung für Service Worker auch die Web Background Sync API unterstützt, müssen Entwickler vor der Verwendung der Schnittstelle sowohl die Existenz der Service-Worker-API als auch die des SyncManager-Interfaces prüfen. Ist es vorhanden, lässt sich innerhalb der Webanwendung über die Service-Worker-Registrierung auf die Instanz des SyncManagers zugreifen. Hier können Synchronisierungsereignisse mit einem bestimmten Bezeichner (Tag) registriert werden. Im Falle des Messenger-Beispiels würde die register()-Methode des SyncManagers nach jeder abgeschickten Nachricht aufgerufen werden:

if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.js');
navigator.serviceWorker.ready.then(registration => {
if ('SyncManager' in window) {
registration.sync.register('messages');
}
});
}

Aufseiten des Service-Worker-Skripts implementiert man einen Ereignis-Handler für das von der Background Sync API definierte sync-Ereignis. Bei der Ereignisregistrierung ist übrigens keine Prüfung auf die Existenz der API erforderlich, das Ereignis wird in Browsern ohne Unterstützung für die Web Background Sync API schlichtweg nicht aufgerufen. Bei bestehender Internetverbindung wird der Ereignis-Handler direkt aufgerufen. Andernfalls wird das Auslösen des Ereignisses solange verzögert, bis der Webbrowser der Ansicht ist, dass wieder eine Verbindung besteht. Mit absoluter Sicherheit lässt sich das aber nie sagen: Trotz hervorragender WiFi-Verbindung muss nicht zwingend eine Verbindung zum Internet bestehen (z.B. Drucker-WLANs). Und trotz EDGE-Empfang müssen Pakete nicht zwingend ihr Ziel finden. Ein Restrisiko, dass die Synchronisation dennoch nicht stattfinden kann, bleibt also.

Sollte beim Durchführen der Synchronisationslogik ein Fehler auftreten, kann der Webbrowser den Ereignis-Handler noch mehrmals aufrufen. Beim letzten Versuch ist die Eigenschaft lastChance in den Ereignisargumenten auf true gesetzt. Auf ihnen ist in der Eigenschaft tag der Bezeichner aus der Webanwendung zu finden. Anhand dessen ließen sich unterschiedliche Synchronisierungsabläufe wählen.

self.addEventListener('sync', event => {
if (event.tag == 'messages') {
event.waitUntil(syncMessages());
}
});

Sowohl der Service Worker als auch die Website teilen sich Zugriff auf dieselbe IndexedDB-Instanz. Die Webanwendung kann hochzuladende Inhalte in der Datenbank hinterlegen. Von dort kann der Service Worker diese dann mit dem Backend austauschen und neue oder geänderte Inhalte auf dem Rückweg in der Datenbank hinterlegen.

Da bei jeder Netzabfrage die IP-Adresse übermittelt wird, könnten Entwickler auf diese Art ein begrenztes Bewegungsprofil der Anwender erstellen. Da weder zur Installation des Service Worker noch zur Nutzung der Background Sync API eine vorherige Berechtigungsabfrage geschieht, haben Anwender keine Möglichkeit, diesem entgegenzuwirken. Auch gibt es bei der Schnittstelle keinen visuellen Indikator, dass eine PWA gerade Ereignisse im Hintergrund ausführt.

Derzeit wird die Web Background Sync API lediglich von Google Chrome und darauf basierenden Browsern wie Opera oder Microsoft Edge unterstützt. Es gilt als unwahrscheinlich, dass Apple die Schnittstelle nutzen wird. Auch in Mozilla Firefox wurde die Implementierung der Schnittstelle pausiert. Deswegen und zur Unterstützung älterer Browser müssen Entwickler immer noch einen zweiten Weg innerhalb der Webanwendung implementieren, über den sich die Daten mit dem Anwendungsserver austauschen lassen. Dafür muss die Anwendung dann aber geöffnet sein.

Mit der Background Fetch API und der Periodic Sync API stehen glücklicherweise Alternativen zur Verfügung, die sich möglicherweise ihren Weg in weitere Browser bahnen könnten. Diese stelle ich in den nächsten beiden Teilen dieser Serie vor. ()