Änderungen an „cache.addAll()“ und „importScripts()“ in Chrome 71

Entwickler, die Service Worker und die Cache Storage API verwenden, sollten auf zwei kleine Änderungen in Chrome 71 achten. Mit beiden Änderungen wird die Implementierung von Chrome näher an die Spezifikationen und andere Browser angepasst.

Asynchrone ImportScripts()-Methode nicht zulassen

importScripts() weist das Service-Worker-Hauptskript an, die aktuelle Ausführung anzuhalten, zusätzlichen Code von einer bestimmten URL herunterzuladen und im aktuellen globalen Geltungsbereich vollständig auszuführen. Sobald dies abgeschlossen ist, setzt das Hauptskript für den Service Worker die Ausführung fort. importScripts() ist praktisch, wenn Sie Ihr Hauptskript für den Service Worker aus organisatorischen Gründen in kleinere Teile aufteilen oder Drittanbietercode einbinden möchten, um Ihrem Service Worker weitere Funktionen hinzuzufügen.

Browser versuchen, mögliche Leistungsprobleme zu minimieren, die durch das Herunterladen und Ausführen von synchronem Code entstehen. Dazu werden alle über importScripts() abgerufenen Daten automatisch im Cache gespeichert. Das bedeutet, dass nach dem ersten Download nur wenig Aufwand für die Ausführung des importierten Codes erforderlich ist.

Damit dies funktioniert, muss der Browser jedoch wissen, dass nach der Erstinstallation kein "Überraschungscode" in den Service Worker importiert wird. Gemäß der Service Worker-Spezifikation sollte importScripts() nur bei der synchronen Ausführung des Service Worker-Skripts auf oberster Ebene oder bei Bedarf asynchron innerhalb des Handlers install funktionieren.

Vor Chrome 71 war es möglich, importScripts() asynchron außerhalb des install-Handlers aufzurufen. Ab Chrome 71 lösen diese Aufrufe eine Laufzeitausnahme aus, es sei denn, dieselbe URL wurde zuvor in einen install-Handler importiert, da sie dem Verhalten in anderen Browsern entspricht.

Anstelle von Code wie diesem:

// This only works in Chrome 70 and below.
self.addEventListener('fetch', event => {
  importScripts('my-fetch-logic.js');
  event.respondWith(self.customFetchLogic(event));
});

Ihr Service Worker-Code sollte wie folgt aussehen:

// Move the importScripts() to the top-level scope.
// (Alternatively, import the same URL in the install handler.)
importScripts('my-fetch-logic.js');
self.addEventListener('fetch', event => {
  event.respondWith(self.customFetchLogic(event));
});

Wiederholte an „cache.addAll()“ übergebene URLs verwerfen

Wenn Sie die Cache Storage API zusammen mit einem Service Worker verwenden, gibt es eine weitere kleine Änderung in Chrome 71, um die API an die entsprechende Spezifikation anzupassen. Wenn dieselbe URL mehrmals an einen einzelnen Aufruf von cache.addAll() übergeben wird, wird in der Spezifikation festgelegt, dass das vom Aufruf zurückgegebene Versprechen abgelehnt werden soll.

Vor Chrome 71 wurde dies nicht erkannt und doppelte URLs wurden praktisch ignoriert.

Screenshot der Warnmeldung in der Chrome-Konsole
Ab Chrome 71 wird in der Console eine Warnmeldung protokolliert.

Dieses Logging ist ein Vorhaben in Chrome 72, in dem doppelte URLs anstelle einer protokollierten Warnung dazu führen, dass cache.addAll() abgelehnt wird. Wenn Sie cache.addAll() als Teil einer Promise-Kette aufrufen, die an InstallEvent.waitUntil() übergeben wird, kann diese Ablehnung dazu führen, dass der Service Worker nicht installiert wird.

Mögliche Probleme:

const urlsToCache = [
  '/index.html',
  '/main.css',
  '/app.js',
  '/index.html', // Oops! This is listed twice and should be removed.
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('my-cache').then(cache => cache.addAll(urlsToCache))
  );
});

Diese Einschränkung gilt nur für die tatsächlichen URLs, die an cache.addAll() übergeben werden. Das Caching von zwei äquivalenten Antworten mit unterschiedlichen URLs, z. B. '/' und '/index.html', löst keine Ablehnung aus.

Testen Sie Ihre Service Worker-Implementierung umfassend

Service Worker sind derzeit in allen wichtigen Evergreen-Browsern weit implementiert. Wenn Sie Ihre progressive Web-App regelmäßig in verschiedenen Browsern testen oder wenn eine große Anzahl von Nutzern Chrome nicht verwendet, haben Sie diese Inkonsistenz wahrscheinlich bereits erkannt und Ihren Code aktualisiert. Falls Sie dieses Verhalten in anderen Browsern aber vielleicht nicht bemerkt haben, möchten wir auf die Änderung hinweisen, bevor Sie das Verhalten von Chrome ändern.