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

Entwickler, die Service Workers und die Cache Storage API verwenden, sollten sich auf zwei kleine Änderungen in Chrome 71 vorbereiten. Durch beide Änderungen wird die Implementierung von Chrome besser an die Spezifikation und andere Browser angepasst.

Asynchrone importScripts() nicht mehr zulässig

importScripts() bewirkt, dass Ihr Haupt-Serviceworker-Script die aktuelle Ausführung pausiert, zusätzlichen Code von einer bestimmten URL herunterlädt und ihn im aktuellen globalen Gültigkeitsbereich bis zum Ende ausführt. Anschließend setzt das Service Worker-Hauptskript die Ausführung fort. importScripts() ist praktisch, wenn Sie Ihr Haupt-Serviceworker-Script aus organisatorischen Gründen in kleinere Teile aufteilen oder Code von Drittanbietern einbinden möchten, um Ihrem Serviceworker Funktionen hinzuzufügen.

Browser versuchen, die möglichen Leistungsprobleme beim Herunterladen und Ausführen synchronen Codes zu minimieren, indem alles, was über importScripts() abgerufen wird, automatisch im Cache gespeichert wird. Nach dem ersten Download ist der Overhead bei der Ausführung des importierten Codes also sehr gering.

Damit das funktioniert, muss der Browser jedoch wissen, dass nach der ersten Installation kein „Überraschungscode“ in den Service Worker importiert wird. Gemäß der Service Worker-Spezifikation sollte importScripts() nur während der synchronen Ausführung des Service Worker-Scripts der obersten Ebene oder bei Bedarf asynchron innerhalb des install-Handlers aufgerufen werden.

Vor Chrome 71 funktionierte der asynchrone Aufruf von importScripts() außerhalb des install-Handlers. Ab Chrome 71 werfen diese Aufrufe eine Laufzeitausnahme, es sei denn, dieselbe URL wurde zuvor in einen install-Handler importiert. Das entspricht dem Verhalten in anderen Browsern.

Anstatt Code wie diesen:

// 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 so 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 URLs, die an cache.addAll() übergeben werden, werden eingestellt

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

Vor Chrome 71 wurde das nicht erkannt und die doppelten URLs wurden effektiv ignoriert.

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

Diese Protokollierung ist ein Vorbote für Chrome 72, in dem doppelte URLs nicht nur zu einer protokollierten Warnung, sondern zur Ablehnung von cache.addAll() führen. Wenn Sie cache.addAll() wie üblich als Teil einer Promise-Kette aufrufen, die an InstallEvent.waitUntil() übergeben wird, kann diese Ablehnung dazu führen, dass Ihr Service Worker nicht installiert wird.

In folgenden Fällen kann es zu Problemen kommen:

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 wie '/' und '/index.html' führt nicht zu einer Ablehnung.

Service Worker-Implementierung umfassend testen

Service Worker sind derzeit in allen gängigen „Evergreen“-Browsern weitgehend implementiert. Wenn Sie Ihre progressive Webanwendung regelmäßig in mehreren Browsern testen oder eine große Anzahl von Nutzern haben, die Chrome nicht verwenden, haben Sie die Inkonsistenz wahrscheinlich bereits erkannt und Ihren Code aktualisiert. Falls Sie dieses Verhalten in anderen Browsern nicht bemerkt haben, möchten wir Sie vor der Änderung des Chrome-Verhaltens darauf hinweisen.