Asynchroner Zugriff auf HTTP-Cookies

Victor Costan

Was ist die Cookie Store API?

Die Cookie Store API stellt HTTP-Cookies für Service Worker bereit und bietet eine asynchrone Alternative zu document.cookie. Mit der API können Sie Folgendes einfacher tun:

  • Vermeiden Sie Ruckler im Hauptthread, indem Sie asynchron auf Cookies zugreifen.
  • Vermeiden Sie das Abfragen von Cookies, da Änderungen an Cookies beobachtet werden können.
  • Auf Cookies von Service Workern zugreifen.

Erläuterung lesen

Aktueller Status

Schritt Status
1. Erläuternde Mitteilung erstellen Abschließen
2. Ersten Entwurf der Spezifikation erstellen Abschließen
**3. Feedback einholen und Spezifikation optimieren** **In Bearbeitung**
4. Ursprungstest Pausiert
5. Starten Nicht gestartet

Wie verwende ich den asynchronen Cookie-Speicher?

Testzeitraum für die Quelle aktivieren

Wenn Sie die API lokal testen möchten, können Sie sie über die Befehlszeile aktivieren:

chrome --enable-blink-features=CookieStore

Wenn Sie dieses Flag in der Befehlszeile übergeben, wird die API global in Chrome für die aktuelle Sitzung aktiviert.

Alternativ können Sie das Flag #enable-experimental-web-platform-features in chrome://flags aktivieren.

Sie benötigen (wahrscheinlich) keine Cookies

Bevor wir uns mit der neuen API befassen, möchte ich darauf hinweisen, dass Cookies immer noch das schlechteste clientseitige Speicherelement der Webplattform sind und nur als letztes Mittel eingesetzt werden sollten. Das ist kein Zufall: Cookies waren der erste clientseitige Speichermechanismus im Web und wir haben seitdem viel dazugelernt.

Die Hauptgründe für die Vermeidung von Cookies sind:

  • Cookies stellen das Speicherschema in Ihre Back-End-API ein. Jede HTTP-Anfrage enthält einen Snapshot des Cookie-Jars. So können Back-End-Entwickler ganz einfach Abhängigkeiten vom aktuellen Cookie-Format einführen. Danach kann Ihr Frontend sein Speicherschema nicht mehr ändern, ohne eine entsprechende Änderung für das Backend bereitzustellen.

  • Cookies haben ein komplexes Sicherheitsmodell. Moderne Webplattformfunktionen folgen derselben Ursprungsrichtlinie, was bedeutet, dass jede Anwendung eine eigene Sandbox erhält und völlig unabhängig von anderen Anwendungen ist, die der Nutzer möglicherweise ausführt. Cookie-Bereiche sorgen für eine wesentlich komplexere Sicherheitsgeschichte. Eine einfache Zusammenfassung, die den Umfang dieses Artikels verdoppeln würde.

  • Cookies haben hohe Leistungskosten. Browser müssen in jeder HTTP-Anfrage einen Snapshot Ihrer Cookies enthalten. Daher müssen alle Änderungen an Cookies über die Speicher- und Netzwerkstacks weitergegeben werden. Moderne Browser haben hochoptimierte Cookie-Speicherimplementierungen, aber wir werden Cookies nie so effizient machen können wie die anderen Speichermechanismen, die nicht mit dem Netzwerkstack kommunizieren müssen.

Aus all den oben genannten Gründen sollten moderne Webanwendungen keine Cookies verwenden, sondern stattdessen eine Sitzungs-ID in IndexedDB speichern und die ID über die fetch API explizit dem Header oder Body bestimmter HTTP-Anfragen hinzufügen.

Sie lesen diesen Artikel aber trotzdem, weil Sie einen guten Grund haben, Cookies zu verwenden.

Die alte document.cookie-API ist eine ziemlich sichere Quelle für Ruckler in Ihrer Anwendung. Wenn Sie beispielsweise den document.cookie-Getter verwenden, muss der Browser die Ausführung von JavaScript beenden, bis er die angeforderten Cookie-Informationen hat. Dies kann einen Prozess-Hop oder einen Datenträgerlesevorgang erfordern, wodurch Ihre UI zu Verzögerungen führt.

Eine einfache Lösung für dieses Problem ist der Wechsel vom document.cookie-Getter zur asynchronen Cookie Store API.

await cookieStore.get('session_id');

// {
//   domain: "example.com",
//   expires: 1593745721000,
//   name: "session_id",
//   path: "/",
//   sameSite: "unrestricted",
//   secure: true,
//   value: "yxlgco2xtqb.ly25tv3tkb8"
// }

Der document.cookie-Setter kann auf ähnliche Weise ersetzt werden. Beachten Sie, dass die Änderung erst dann garantiert angewendet wird, wenn das von cookieStore.set zurückgegebene Promise aufgelöst wird.

await cookieStore.set({name: 'opt_out', value: '1'});

// undefined

Beobachten, nicht befragen

Eine beliebte Anwendung für den Zugriff auf Cookies über JavaScript ist die Erkennung, wenn sich ein Nutzer abmeldet, und die UI aktualisiert. Derzeit wird dies durch das Abfragen von document.cookie durchgeführt, was zu Rucklern führt und sich negativ auf die Akkulaufzeit auswirkt.

Die Cookie Store API bietet eine alternative Methode zum Beobachten von Cookie-Änderungen, die keine Abfragen erfordert.

cookieStore.addEventListener('change', event => {
  for (const cookie of event.changed) {
    if (cookie.name === 'session_id') sessionCookieChanged(cookie.value);
  }
  for (const cookie of event.deleted) {
    if (cookie.name === 'session_id') sessionCookieChanged(null);
  }
});

Willkommen, Service Worker

Aufgrund des synchronen Designs ist die document.cookie API nicht für Dienst-Worker verfügbar. Die Cookie Store API ist asynchron und daher in Serviceworkern zulässig.

Die Interaktion mit den Cookies funktioniert in Dokumentenkontexten und in Service Workern auf die gleiche Weise.

// Works in documents and service workers.
async function logOut() {
  await cookieStore.delete('session_id');
}

Die Beobachtung von Cookie-Änderungen ist bei Service Workern jedoch etwas anders. Das Aufwecken eines Service Workers kann ziemlich teuer sein. Daher müssen wir die Cookie-Änderungen, an denen der Worker interessiert ist, explizit beschreiben.

Im folgenden Beispiel überwacht eine Anwendung, die Nutzerdaten mit IndexedDB im Cache speichert, Änderungen am Sitzungscookie und verwirft die im Cache gespeicherten Daten, wenn sich der Nutzer abmeldet.

// Specify the cookie changes we're interested in during the install event.
self.addEventListener('install', event => {
  event.waitUntil(cookieStore.subscribeToChanges([{name: 'session_id'}]));
});

// Delete cached data when the user logs out.
self.addEventListener('cookiechange', event => {
  for (const cookie of event.deleted) {
    if (cookie.name === 'session_id') {
      indexedDB.deleteDatabase('user_cache');
      break;
    }
  }
});

Best Practices

Bald verfügbar.

Feedback

Wir würden uns über Ihr Feedback freuen, wenn Sie diese API ausprobieren. Bitte leiten Sie Feedback zur API-Form an das Spezifikations-Repository weiter und melden Sie Implementierungsfehler an die Blink-Komponente Blink>Storage>CookiesAPI.

Wir sind besonders an Leistungsmessungen und Anwendungsfällen interessiert, die über die im Erläuterungsvideo beschriebenen hinausgehen.

Zusätzliche Ressourcen