Der Service-Worker

Mit Hilfe eines Service-Workers, können Webanwendungen so erweitert werden, dass sie vorrangig gecachte Inhalte nutzen und so auch offline bedienbar sind, bevor weitere Daten aus dem Netzwerk geladen werden (Offline First).

Aus Sicherheitsgründen sind Service-Worker auf HTTPS beschränk. Dies gilt nicht, wenn die Anwendung lokal, also unter localhost, läuft.

Der Service-Worker ist ein spezieller Web Worker. Wie dieser läuft er ebenfalls in einem eigenen Thread und erlaubt keine direkte Manipulation des DOM.
Vor der Verwendung muss er installiert werden und bezieht sich auf den aktuellen Scope (Protokoll, Hostname und Port) und den Pfad, unterhalb dessen eine Website ausgeführt wird. Der Service-Worker bezieht sich zudem nich auf einen Browser-Tab oder das Browser-Fenster.
Hauptsächlich wird er für zwei Aufgaben eingesetzt:

  • als Proxy zwischen dem Webbrowser und dem Server
  • als Empfänger von Benachrichtigungen des Servers im Hintergrund

Diese Benachrichtigungen kann er empfangen, wenn aktuell keine Seite der jeweiligen Domain geöffnet ist. So können beispielsweise Push-Benachrichtigungen realisiert oder Daten im Hintergrund synchronisiert werden.
Der Service-Worker verfügt über einen eigenen Cache und kann sich zwischen jeden ausgehenden Netzwerk-Request schalten. Er selbst kann dann entscheiden, ob er eine Anfrage aus seinem Cache beantwortet oder die Anfrage an das Netzwerk geleitet wird. Auf diese Art lässt sich beispielsweise die Offlinefähigkeit der App realisieren.

Service-Worker erstellen und einbinden

Ob ein Browser den Service-Worker unterstützt, muss die PWA abfragen, bevor versucht wird, den Service-Worker zu registrieren:


<script>
if ('serviceWorker' in navigator) {
	navigator.serviceWorker.register('/serviceworker.js');
}
</script>

Beispiel für eine Pushbenachrichtigung:


const showNotification = async () => {
	const swRegistration = await navigator.serviceWorker.register('/serviceworker.js');
	const permission = await window.Notification.requestPermission();
	if (permission === 'granted') {
		swRegistration.showNotification('This is the title', {
			'body': 'this is the message'
		}, swRegistration);
	}
}
showNotification();

Einfachste Variante des Service-Workers

Im Service-Worker selber sollte das Event "fetch" abgefragt werden, welcher bei jeder HTTP-Abfrage ausgeführt wird. Hier ist es dann möglich, auf eine nicht vorhandene Internetverbindungen zu reagieren:


this.addEventListener('fetch', function(event) {
	// Hier wird die HTTP-Antwort abgefangen und
	// kann bspw. mit einer Antwort aus dem Cache ersetzt werden
});