HTTP Cookie への非同期アクセス

Victor Costan

Cookie Store API とは

Cookie Store API は HTTP Cookie を Service Worker に公開し、document.cookie に代わる非同期的な手段を提供します。この API を使用すると、次のことが簡単になります。

  • Cookie に非同期でアクセスして、メインスレッドでのジャンクを避ける。
  • Cookie の変更は確認できるため、Cookie をポーリングするのは避けます。
  • Service Worker の Cookie にアクセスする。

説明を読む

現在のステータス

ステップ ステータス
1. 説明を作成 完了
2. 仕様の初期ドラフトを作成 完了
**3. フィードバックを収集して仕様について反復する** **進行中**
4. オリジン トライアル 一時停止
5. リリース 未対応

非同期の Cookie ストアを使用するにはどうすればよいですか?

オリジン トライアルを有効にする

ローカルに試すには、コマンドラインで API を有効にします。

chrome --enable-blink-features=CookieStore

このフラグをコマンドラインで渡すと、現在のセッションで Chrome の API がグローバルに有効になります。

また、chrome://flags#enable-experimental-web-platform-features フラグを有効にすることもできます。

(おそらく)Cookie は必要ないでしょう。

新しい API の説明に入る前に、ウェブ プラットフォームのクライアント側ストレージ プリミティブで Cookie は最悪のものであることに変わりはありません。Cookie は最後の手段として使用することをおすすめします。これは偶然ではありません。Cookie はウェブの最初のクライアントサイド ストレージ メカニズムであり、それ以降、Google は多くのことを学んできました。

Cookie を使用しない主な理由は次のとおりです。

  • Cookie はストレージ スキーマをバックエンド API に取り込みます。 各 HTTP リクエストには Cookie JAR のスナップショットが含まれています。これにより、バックエンド エンジニアが現在の Cookie 形式への依存関係を簡単に導入できます。この場合、フロントエンドでストレージ スキーマを変更するには、一致する変更をバックエンドにデプロイする必要があります。

  • Cookie のセキュリティ モデルは複雑なモデルです。最新のウェブ プラットフォーム機能は、同じオリジン ポリシーに従います。つまり、各アプリは独自のサンドボックスを取得し、ユーザーが実行している他のアプリケーションから完全に独立しています。Cookie スコープは、セキュリティの話が非常に複雑になるため、まとめにしただけでもこの記事は 2 倍になってしまいます。

  • Cookie はパフォーマンスの低下を招きます。ブラウザでは、すべての HTTP リクエストに Cookie のスナップショットを含める必要があるため、Cookie への変更はすべてストレージ スタックとネットワーク スタックに伝播する必要があります。最新のブラウザでは Cookie ストアの実装が高度に最適化されていますが、ネットワーク スタックと通信する必要のない他のストレージ メカニズムほど Cookie の効率を高めることはできません。

上述のすべての理由から、最新のウェブ アプリケーションでは Cookie を使用せず、代わりにセッション識別子を IndexedDB に保存し、その識別子を fetch API を介して特定の HTTP リクエストのヘッダーまたは本文に明示的に追加する必要があります。

しかし、Cookie を使用する正当な理由があるから、まだこの記事は読んでいません。

実績ある document.cookie API は、アプリのジャンク発生源としてかなり保証されています。たとえば、document.cookie ゲッターを使用する場合、ブラウザはリクエストした Cookie 情報を取得するまで JavaScript の実行を停止する必要があります。これにより、プロセスホップまたはディスク読み取りが発生し、UI がジャンクします。

この問題は、document.cookie ゲッターから非同期 Cookie Store API に切り替えることで簡単に解決できます。

await cookieStore.get('session_id');

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

document.cookie セッターも同様の方法で置換できます。変更は、cookieStore.set によって返された Promise が解決された後にのみ適用されることが保証されていることに注意してください。

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

// undefined

観察し、アンケートは行わない

JavaScript から Cookie にアクセスする一般的なアプリケーションは、ユーザーのログアウトを検出して UI を更新するというものです。これは現在、document.cookie をポーリングすることによって行われています。これによりジャンクが発生し、バッテリー駆動時間に悪影響を及ぼします。

Cookie Store API は、ポーリングを必要としない代替手段で Cookie の変更を監視します。

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);
  }
});

Service Worker へようこそ

同期設計のため、document.cookie API は Service Worker で利用できません。Cookie Store API は非同期であるため、Service Worker で許可されます。

Cookie の操作は、ドキュメントのコンテキストでも Service Worker でも同じように機能します。

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

ただし、Cookie の変更の監視は、Service Worker では若干異なります。Service Worker の復帰にはコストがかかるため、Worker が関係する Cookie の変更を明示的に記述する必要があります。

以下の例では、IndexedDB を使用してユーザーデータのキャッシュを行うアプリケーションは、セッション Cookie の変更をモニタリングし、ユーザーがログアウトしたときにキャッシュされたデータを破棄します。

// 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;
    }
  }
});

ベスト プラクティス

近日提供予定です。

フィードバック

この API をお試しになりましたら、ぜひご感想をお聞かせください。API シェイプに関するフィードバックは仕様リポジトリに直接お送りください。また、実装のバグは Blink>Storage>CookiesAPI Blink コンポーネントに報告してください。

Google は特に、説明で概説されていないパフォーマンス測定とユースケースについて学びたいと考えています。

補足資料