Service Worker-Registrierung

Best Practices für das Timing der Service Worker-Registrierung

Dienstworker können wiederholte Besuche Ihrer Webanwendung erheblich beschleunigen. Sie sollten jedoch dafür sorgen, dass die Erstinstallation eines Dienstworkers die Nutzererfahrung beim ersten Besuch nicht beeinträchtigt.

Im Allgemeinen bietet es sich an, die Registrierung für Service Worker nach dem Laden der ersten Seite aufzuhalten, um die beste Nutzerfreundlichkeit zu bieten. Dies gilt insbesondere für Mobilgeräte mit langsameren Netzwerkverbindungen.

Standard-Boilerplate für die Registrierung

Wenn Sie schon einmal etwas über Service Worker gelesen haben, sind Sie wahrscheinlich auf Boilerplate-Code gestoßen, der in etwa so aussieht:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js');
}

Manchmal werden dazu einige console.log()-Anweisungen oder Code verwendet, um ein Update einer vorherigen Service Worker-Registrierung zu erkennen und Nutzer darüber zu informieren, dass sie die Seite aktualisieren müssen. Das sind aber nur geringfügige Abweichungen von den wenigen Standardcodezeilen.

Gibt es einen Unterschied bei navigator.serviceWorker.register? Gibt es Best Practices, die ich beachten sollte? Wie nicht anders zu erwarten (da dieser Artikel nicht hier endet), lautet die Antwort auf beide Fragen „Ja“.

Erster Besuch eines Nutzers

Betrachten wir den ersten Besuch eines Nutzers in einer Webanwendung. Es gibt noch keinen Service Worker und der Browser kann nicht im Voraus wissen, ob es einen Service Worker geben wird, der später installiert wird.

Als Entwickler sollten Sie dafür sorgen, dass der Browser schnell die minimalen kritischen Ressourcen erhält, die zum Anzeigen einer interaktiven Seite erforderlich sind. Alles, was das Abrufen dieser Antworten verlangsamt, ist der Feind einer schnellen Interaktion.

Angenommen, beim Herunterladen des JavaScripts oder der Bilder, die für das Rendern Ihrer Seite erforderlich sind, startet Ihr Browser einen Hintergrund-Thread oder -Prozess. Der Einfachheit halber nehmen wir an, dass es sich um einen Thread handelt. Angenommen, Sie verwenden kein leistungsstarkes Desktop-Gerät, sondern ein leistungsschwaches Smartphone, das viele Menschen als ihr Hauptgerät betrachten. Durch das Starten dieses zusätzlichen Threads kommt es zu Konflikten bei CPU-Zeit und Arbeitsspeicher, die Ihr Browser sonst für das Rendern einer interaktiven Webseite verwenden könnte.

Ein inaktiver Hintergrund-Thread wird wahrscheinlich keinen großen Unterschied machen. Was ist aber, wenn dieser Thread nicht inaktiv ist, sondern stattdessen entscheidet, dass er auch Ressourcen aus dem Netzwerk herunterladen soll? Bedenken hinsichtlich der CPU- oder Arbeitsspeicherauslastung sollten in den Hintergrund treten, da die Bandbreite vieler Mobilgeräte begrenzt ist. Die Bandbreite ist kostbar. Setzen Sie sie also nicht durch den gleichzeitigen Download sekundärer Ressourcen unnötig unter Druck.

All dies bedeutet, dass das Starten eines neuen Service Worker-Threads zum Herunterladen und Zwischenspeichern von Ressourcen im Hintergrund Ihrem Ziel förderlich ist, wenn ein Nutzer beim ersten Besuch Ihrer Website die kürzeste Zeit bis zur interaktiven Nutzung bietet.

Verbesserung des Standardtexts

Die Lösung besteht darin, den Start des Dienstarbeiters zu steuern, indem Sie festlegen, wann navigator.serviceWorker.register() aufgerufen werden soll. Als Faustregel gilt, die Registrierung so lange zu verzögern, bis load event auf window ausgelöst wird. Das würde so aussehen:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}

Der richtige Zeitpunkt für die Registrierung des Dienstarbeiters kann jedoch auch davon abhängen, was Ihre Webanwendung direkt nach dem Laden tut. Die Web-App der Google I/O 2016 enthält beispielsweise eine kurze Animation, bevor der Hauptbildschirm angezeigt wird. Unser Team hat festgestellt, dass der Start der Service Worker-Registrierung während der Animation zu Verzögerungen auf Low-End-Mobilgeräten führen kann. Anstatt den Nutzern eine schlechte Erfahrung zu bieten, haben wir die Registrierung des Dienst-Workers auf nach der Animation verschoben, wenn der Browser am ehesten einige Sekunden inaktiv war.

Wenn Ihre Webanwendung ein Framework verwendet, das nach dem Laden der Seite eine zusätzliche Einrichtung durchführt, suchen Sie nach einem frameworkspezifischen Ereignis, das signalisiert, dass diese Arbeit abgeschlossen ist.

Nachfolgende Besuche

Bisher haben wir uns auf den ersten Besuch konzentriert. Welche Auswirkungen hat die verzögerte Registrierung von Dienstmitarbeitern auf wiederholte Besuche Ihrer Website? Das mag vielleicht einige Menschen überraschen, aber es sollte überhaupt keine Auswirkungen haben.

Wenn ein Service Worker registriert ist, durchläuft er die Lebenszyklusereignisse install und activate. Sobald ein Service Worker aktiviert ist, kann er fetch-Ereignisse für alle nachfolgenden Besuche Ihrer Webanwendung verarbeiten. Er wird bevor die Anfrage für Seiten in seinem Umfang erfolgt gestartet. Das ist eigentlich ganz logisch. Wenn der vorhandene Dienst-Worker nicht bereits vor dem Besuch einer Seite ausgeführt wurde, kann er keine fetch-Ereignisse für Navigationsanfragen ausführen.

Sobald also ein aktiver Dienst-Worker vorhanden ist, spielt es keine Rolle, wann Sie navigator.serviceWorker.register() aufrufen oder ob Sie ihn überhaupt aufrufen. Wenn Sie die URL des Service Worker-Scripts nicht ändern, ist navigator.serviceWorker.register() bei nachfolgenden Besuchen inaktiv. Wann es aufgerufen wird, spielt keine Rolle.

Gründe für eine frühzeitige Anmeldung

Gibt es Szenarien, in denen es sinnvoll ist, Ihren Dienst-Worker so früh wie möglich zu registrieren? Ein Beispiel wäre, wenn Ihr Service Worker clients.claim() verwendet, um die Kontrolle über die Seite beim ersten Besuch zu übernehmen, und der Service Worker im fetch-Handler aggressiv Laufzeit-Caching durchführt. In diesem Fall ist es von Vorteil, den Dienst-Worker so schnell wie möglich zu aktivieren, um seine Laufzeit-Caches mit Ressourcen zu füllen, die später nützlich sein könnten. Wenn Ihre Webanwendung in diese Kategorie fällt, sollten Sie sich vergewissern, dass der install-Handler Ihres Service Workers keine Ressourcen anfordert, die mit den Anfragen der Startseite um die Bandbreite konkurrieren.

Testen

Eine gute Möglichkeit, einen ersten Besuch zu simulieren, besteht darin, Ihre Webanwendung in einem Chrome-Inkognitofenster zu öffnen und sich den Netzwerkverkehr in den Chrome-Entwicklertools anzusehen. Als Webentwickler laden Sie wahrscheinlich mehrmals täglich eine lokale Instanz Ihrer Webanwendung neu. Wenn Sie Ihre Website jedoch noch einmal aufrufen, wenn bereits ein Service Worker und vollständig gefüllte Caches vorhanden sind, erhalten Sie nicht die gleiche Leistung wie ein neuer Nutzer. Außerdem ist es dann leicht, ein potenzielles Problem zu übersehen.

Hier ein Beispiel, das den Unterschied zeigt, den der Zeitpunkt der Registrierung ausmachen kann. Beide Screenshots wurden beim Besuch einer Beispiel-App im Inkognitomodus aufgenommen. Dabei wurde die Netzwerkdrosselung verwendet, um eine langsame Verbindung zu simulieren.

Netzwerkverkehr mit vorzeitiger Registrierung

Der Screenshot oben zeigt den Netzwerkverkehr, als das Beispiel so geändert wurde, dass die Registrierung des Dienstarbeiters so schnell wie möglich durchgeführt wurde. Sie sehen Precaching-Anfragen (die Einträge mit dem Zahnradsymbol daneben, die vom install-Handler des Service Workers stammen) zwischen Anfragen für die anderen Ressourcen, die zum Anzeigen der Seite erforderlich sind.

Netzwerkverkehr mit verspäteter Registrierung

Im Screenshot oben wurde die Registrierung des Service Workers verzögert, bis die Seite geladen war. Wie Sie sehen, werden die Pre-Caching-Anfragen erst gestartet, wenn alle Ressourcen aus dem Netzwerk abgerufen wurden. So wird jeglicher Bandbreitenkonflikt vermieden. Da sich einige der Elemente, die wir vorab im Cache speichern, bereits im HTTP-Cache des Browsers befinden (die Elemente mit (from disk cache) in der Spalte „Größe“), können wir den Cache des Service Workers füllen, ohne noch einmal das Netzwerk aufrufen zu müssen.

Bonuspunkte, wenn Sie diese Art von Test auf einem echten Low-End-Gerät in einem echten Mobilfunknetz ausführen. Sie können die Remote-Debugging-Funktionen von Chrome nutzen, um ein Android-Smartphone über USB mit Ihrem Computer zu verbinden und dafür zu sorgen, dass die von Ihnen durchgeführten Tests die tatsächliche Nutzung durch viele Ihrer Nutzer widerspiegeln.

Fazit

Deshalb sollte es oberste Priorität haben, Nutzern beim ersten Besuch ein optimales Erlebnis zu bieten. Sie können dies erreichen, indem Sie die Registrierung des Dienst-Workers verzögern, bis die Seite beim ersten Besuch geladen wurde. Sie profitieren weiterhin von allen Vorteilen eines Service Workers bei wiederholten Besuchen.

Eine einfache Möglichkeit, die Erstregistrierung Ihres Service Workers so lange zu verzögern, bis die erste Seite geladen ist:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}