Bereitstellung

Progressive Web-Apps sind zuverlässig. Sie können Assets schnell laden, Nutzer bei Laune halten und auch bei schlechten Netzwerkverbindungen sofort Feedback geben. Wie ist das möglich? Das liegt am Service Worker-Ereignis fetch.

Das Abrufereignis

Browser Support

  • Chrome: 40.
  • Edge: 17.
  • Firefox: 44.
  • Safari: 11.1.

Source

Mit dem Ereignis fetch können wir jede Netzwerkanfrage abfangen, die von der PWA im Bereich des Dienstarbeiters gesendet wird, sowohl für Anfragen mit gleicher als auch mit unterschiedlicher Herkunft. Neben Navigations- und Asset-Anfragen ermöglicht das Abrufen von einem installierten Service Worker auch das Rendern von Seitenaufrufen nach dem ersten Laden einer Website ohne Netzwerkanrufe.

Der fetch-Handler empfängt alle Anfragen von einer App, einschließlich URLs und HTTP-Headern, und lässt den App-Entwickler entscheiden, wie sie verarbeitet werden sollen.

Der Dienst-Worker befindet sich zwischen dem Client und dem Netzwerk.

Ihr Service Worker kann eine Anfrage an das Netzwerk weiterleiten, mit einer zuvor im Cache gespeicherten Antwort antworten oder eine neue Antwort erstellen. Die Entscheidung liegt ganz bei dir. Hier ein einfaches Beispiel:

self.addEventListener("fetch", event => {
    console.log(`URL requested: ${event.request.url}`);
});

Auf eine Anfrage antworten

Wenn eine Anfrage an Ihren Service Worker gesendet wird, haben Sie zwei Möglichkeiten: Sie können sie ignorieren, wodurch sie an das Netzwerk weitergeleitet wird, oder Sie können darauf reagieren. Wenn Sie Anfragen über Ihren Service Worker beantworten, können Sie festlegen, was und wie es an Ihre PWA zurückgegeben wird, auch wenn der Nutzer offline ist.

Wenn Sie auf eine eingehende Anfrage reagieren möchten, rufen Sie event.respondWith() in einem fetch-Ereignis-Handler auf. So gehts:

// fetch event handler in your service worker file
self.addEventListener("fetch", event => {
    const response = .... // a response or a Promise of response
    event.respondWith(response);
});

Du musst respondWith() synchron aufrufen und ein Response-Objekt zurückgeben. Sie können respondWith() jedoch nicht nach Abschluss des Fetch-Ereignis-Handlers aufrufen, z. B. in einem asynchronen Aufruf. Wenn du auf die vollständige Antwort warten musst, kannst du respondWith() ein Versprechen übergeben, das mit einer Antwort aufgelöst wird.

Antworten erstellen

Mit der Fetch API können Sie HTTP-Antworten in Ihrem JavaScript-Code erstellen. Diese Antworten können mit der Cache Storage API im Cache gespeichert und so zurückgegeben werden, als würden sie von einem Webserver stammen.

Erstelle zum Erstellen einer Antwort ein neues Response-Objekt und lege den Textkörper sowie Optionen wie Status und Header fest:

const simpleResponse = new Response("Body of the HTTP response");

const options = {
   status: 200,
   headers: {
    'Content-type': 'text/html'
   }
};
const htmlResponse = new Response("<b>HTML</b> content", options)

Antworten aus dem Cache

Nachdem Sie nun wissen, wie Sie HTTP-Antworten von einem Service Worker ausliefern, ist es an der Zeit, die Caching Storage-Benutzeroberfläche zu verwenden, um Assets auf dem Gerät zu speichern.

Mit der Cache Storage API können Sie prüfen, ob die von der PWA empfangene Anfrage im Cache verfügbar ist. Ist das der Fall, antworten Sie mit ihr auf respondWith(). Dazu müssen Sie zuerst im Cache suchen. Die Funktion match(), die in der caches-Oberfläche auf oberster Ebene verfügbar ist, sucht in allen Geschäften in Ihrem Ursprung oder in einem einzelnen offenen Cacheobjekt.

Die Funktion match() empfängt eine HTTP-Anfrage oder eine URL als Argument und gibt ein Versprechen zurück, das mit der dem entsprechenden Schlüssel zugeordneten Antwort aufgelöst wird.

// Global search on all caches in the current origin
caches.match(urlOrRequest).then(response => {
   console.log(response ? response : "It's not in the cache");
});

// Cache-specific search
caches.open("pwa-assets").then(cache => {
  cache.match(urlOrRequest).then(response => {
    console.log(response ? response : "It's not in the cache");
  });
});

Caching-Strategien

Das Bereitstellen von Dateien nur aus dem Browser-Cache ist nicht für jeden Anwendungsfall geeignet. Beispielsweise kann der Nutzer oder der Browser den Cache leeren. Daher sollten Sie Ihre eigenen Strategien für die Bereitstellung von Assets für Ihre PWA definieren. Sie sind nicht auf eine Caching-Strategie beschränkt. Sie können für verschiedene URL-Muster unterschiedliche definieren. Sie können beispielsweise eine Strategie für die minimalen UI-Assets, eine andere für API-Aufrufe und eine dritte für Bild- und Daten-URLs haben. Lesen Sie dazu event.request.url in ServiceWorkerGlobalScope.onfetch und parsen Sie sie mit regulären Ausdrücken oder einem URL-Muster. (Zum Zeitpunkt der Erstellung dieses Artikels wird das URL-Muster nicht auf allen Plattformen unterstützt.)

Die gängigsten Strategien sind:

Cache zuerst
Sucht zuerst nach einer im Cache gespeicherten Antwort und greift auf das Netzwerk zurück, falls keine gefunden wird.
Netzwerk zuerst
Erfordert zuerst eine Antwort vom Netzwerk und sucht dann, falls keine Antwort zurückgegeben wird, im Cache nach einer Antwort.
Veraltet bei Neuvalidierung
Eine Antwort wird aus dem Cache bereitgestellt, während im Hintergrund die neueste Version angefordert und für die nächste Anfrage des Assets im Cache gespeichert wird.
Nur Netzwerk
Antwortet immer mit einer Antwort vom Netzwerk oder es kommt zu einem Fehler. Der Cache wird nie konsultiert.
Nur Cache
Antwortet immer mit einer Antwort aus dem Cache oder es kommt zu einem Fehler. Das Netzwerk wird nie konsultiert. Die Assets, die mit dieser Strategie ausgeliefert werden, müssen dem Cache hinzugefügt werden, bevor sie angefordert werden.

Zuerst im Cache speichern

Bei dieser Strategie sucht der Service Worker im Cache nach der übereinstimmenden Anfrage und gibt die entsprechende Antwort zurück, falls sie im Cache gespeichert ist. Andernfalls wird die Antwort aus dem Netzwerk abgerufen und der Cache für zukünftige Aufrufe optional aktualisiert. Wenn weder eine Cache-Antwort noch eine Netzwerkantwort vorhanden ist, schlägt die Anfrage fehl. Da das Bereitstellen von Assets ohne Zugriff auf das Netzwerk in der Regel schneller ist, wird bei dieser Strategie die Leistung vor Aktualität priorisiert.

Die Cache-first-Strategie

self.addEventListener("fetch", event => {
   event.respondWith(
     caches.match(event.request)
     .then(cachedResponse => {
       // It can update the cache to serve updated content on the next request
         return cachedResponse || fetch(event.request);
     }
   )
  )
});

Netzwerk zuerst

Diese Strategie ist das Spiegelbild der Cache-first-Strategie. Dabei wird geprüft, ob die Anfrage über das Netzwerk erfüllt werden kann. Falls nicht, wird versucht, sie aus dem Cache abzurufen. Cache zuerst. Wenn weder eine Netzwerk- noch eine Cache-Antwort vorhanden ist, schlägt die Anfrage fehl. Da die Antwort vom Netzwerk in der Regel langsamer als vom Cache abgerufen wird, werden bei dieser Strategie aktualisierte Inhalte anstelle der Leistung priorisiert.

Die Netzwerk-first-Strategie

self.addEventListener("fetch", event => {
   event.respondWith(
     fetch(event.request)
     .catch(error => {
       return caches.match(event.request) ;
     })
   );
});

Veraltet bei nochmaliger Validierung

Bei der Strategie „Stale while revalidate“ (Alt, aber noch einmal bestätigen) wird sofort eine im Cache gespeicherte Antwort zurückgegeben. Anschließend wird das Netzwerk auf eine Aktualisierung geprüft und die im Cache gespeicherte Antwort wird ersetzt, falls eine gefunden wird. Bei dieser Strategie wird immer eine Netzwerkanfrage gestellt, da auch dann, wenn eine im Cache gespeicherte Ressource gefunden wird, versucht wird, den Cache mit den Daten aus dem Netzwerk zu aktualisieren, um die aktualisierte Version bei der nächsten Anfrage zu verwenden. Mit dieser Strategie können Sie also von der schnellen Bereitstellung der Cache-first-Strategie profitieren und den Cache im Hintergrund aktualisieren.

Die Strategie „Stale while revalidate“

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(cachedResponse => {
        const networkFetch = fetch(event.request).then(response => {
          // update the cache with a clone of the network response
          const responseClone = response.clone()
          caches.open(url.searchParams.get('name')).then(cache => {
            cache.put(event.request, responseClone)
          })
          return response
        }).catch(function (reason) {
          console.error('ServiceWorker fetch failed: ', reason)
        })
        // prioritize cached response over network
        return cachedResponse || networkFetch
      }
    )
  )
})

Nur Netzwerk

Die reine Netzwerkstrategie ähnelt dem Verhalten von Browsern ohne Service Worker oder Cache Storage API. Bei Anfragen wird nur eine Ressource zurückgegeben, wenn sie aus dem Netzwerk abgerufen werden kann. Das ist oft nützlich für Ressourcen wie nur online verfügbare API-Anfragen.

Die Strategie „Nur Netzwerk“

Nur Cache

Bei der Cache-only-Strategie werden Anfragen nie an das Netzwerk gesendet. Auf alle eingehenden Anfragen wird mit einem vorab ausgefüllten Cache-Element geantwortet. Im folgenden Code wird der fetch-Ereignishandler mit der match-Methode des Cache-Speichers verwendet, um nur auf den Cache zu antworten:

self.addEventListener("fetch", event => {
   event.respondWith(caches.match(event.request));
});

Nur Cache-Strategie.

Benutzerdefinierte Strategien

Die oben genannten sind gängige Caching-Strategien. Sie sind jedoch für Ihren Service Worker und die Verarbeitung von Anfragen verantwortlich. Wenn keine dieser Vorlagen Ihren Anforderungen entspricht, können Sie Ihre eigene erstellen.

Sie können beispielsweise eine Netzwerk-first-Strategie mit einem Zeitlimit verwenden, um aktualisierte Inhalte zu priorisieren, aber nur, wenn die Antwort innerhalb eines von Ihnen festgelegten Grenzwerts angezeigt wird. Sie können auch eine im Cache gespeicherte Antwort mit einer Netzwerkantwort zusammenführen und eine komplexe Antwort vom Service Worker erstellen.

Assets aktualisieren

Es kann schwierig sein, die im Cache Ihrer PWA gespeicherten Assets auf dem neuesten Stand zu halten. Die Strategie „Stale while revalidate“ ist eine Möglichkeit, dies zu tun, aber nicht die einzige. Im Kapitel „Aktualisieren“ erfahren Sie, wie Sie die Inhalte und Assets Ihrer App auf dem neuesten Stand halten.

Ressourcen