什麼是 Cookie Store API?
Cookie Store API 會將 HTTP Cookie 公開給服務工作站,並提供 document.cookie
的非同步替代方案。這個 API 可簡化以下作業:
- 以非同步方式存取 Cookie,避免主執行緒卡頓。
- 系統會觀測 Cookie 的變更,因此請避免輪詢 Cookie。
- 透過服務工作站存取 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 是 Web 的第一個用戶端儲存機制,我們從那時就學到了很多。
避免使用 Cookie 的主要原因包括:
Cookie 會將儲存空間結構定義帶入後端 API。每個 HTTP 要求都會附帶 Cookie Jar 的快照。這樣一來,後端工程師就能輕鬆在目前的 Cookie 格式中引入依附元件。發生這種情況時,前端無法變更儲存格式,除非後端也部署相符的變更。
Cookie 的安全性模型相當複雜。新型網路平台功能遵循相同的來源政策,也就是說,每個應用程式都有專屬的沙箱,而且與使用者可能執行的其他應用程式完全無關。Cookie 範圍不僅可產生更加複雜的安全性故事,而且只是嘗試總結,這項功能會增加本文的兩倍。
Cookie 的效能成本很高。瀏覽器需要在每個 HTTP 要求中加入 Cookie 快照,因此 Cookie 的每項變更都必須在儲存空間和網路堆疊中傳播。現代瀏覽器已實作經過高度最佳化的 Cookie 儲存機制,但我們永遠無法讓 Cookie 的效率與其他儲存機制 (不需要與網路堆疊通訊) 一樣高。
基於上述所有原因,新型網頁應用程式應避免使用 Cookie,而是將工作階段 ID 儲存至 IndexedDB,並透過 fetch API 將 ID 明確新增至特定 HTTP 要求的標頭或內文。
不過,您仍在閱讀本文,表示您有使用 Cookie 的充分理由...
讀取 Cookie 並消除 jank
可長期使用的 document.cookie API 是對應用程式保證的卡頓來源。舉例來說,當您使用 document.cookie
getter 時,瀏覽器必須停止執行 JavaScript,直到其取得您要求的 Cookie 資訊為止。這可能會進行程序躍點或磁碟讀取作業,並導致 UI 發生卡頓。
解決這個問題的簡單方法,就是從 document.cookie
getter 切換至非同步 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
setter 可透過類似方式替換。請注意,變更只會在 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 尚未提供給服務工作站使用。Cookie Store API 是非同步的,因此可在服務 worker 中使用。
在文件內容和服務工作程式中,與 Cookie 互動的運作方式相同。
// Works in documents and service workers.
async function logOut() {
await cookieStore.delete('session_id');
}
不過,在服務工作程式中觀察 Cookie 變更的方式稍有不同。喚醒 Service 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 元件。
我們特別想瞭解成效評估和用途,而非說明文件中所述的用途。
其他資源
- 公開說明
- 規格
- 追蹤錯誤
- chromestatus.com 項目
- WICG Discourse 討論串
- Blink 元件:
Blink>Storage>CookiesAPI