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 iterieren** **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 in der 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:

  • Mithilfe von Cookies wird Ihr Speicherschema in Ihre Back-End-API übertragen. 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. In diesem Fall kann das Front-End sein Speicherschema nicht ändern, ohne eine entsprechende Änderung am Back-End zu implementieren.

  • Cookies haben ein komplexes Sicherheitsmodell. Die Funktionen der modernen Webplattform folgen derselben Richtlinie für Ursprünge. Das 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 deutlich komplexere Sicherheitssituation. Allein der Versuch, diese zu beschreiben, würde die Größe dieses Artikels verdoppeln.

  • 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 Prozesssprung oder eine Festplattenlese erfordern und zu Rucklern der Benutzeroberfläche führen.

Eine einfache Lösung für dieses Problem besteht darin, vom document.cookie-Getter zur asynchronen Cookie Store API zu wechseln.

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. Die Änderung wird erst dann angewendet, wenn das von cookieStore.set zurückgegebene Promise abgeschlossen ist.

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

// undefined

Beobachten, nicht befragen

Eine gängige Anwendung für den Zugriff auf Cookies über JavaScript ist die Erkennung, wenn sich der Nutzer abmeldet, und die Aktualisierung der Benutzeroberfläche. 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 Dokumentkontexten und in Service Workern auf die gleiche Weise.

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

Bei Dienst-Workern ist das Beobachten von Cookie-Änderungen 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

Wenn Sie diese API ausprobieren, lassen Sie uns wissen, was Sie davon halten. Feedback zur API-Form senden Sie bitte an das Repository mit den Spezifikationen. Implementierungsfehler melden Sie bitte über 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