什麼是 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 是網際網路上第一個用於用戶端儲存的機制,我們也從中學到很多。
避免使用 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 的熱門應用程式會偵測使用者登出時機,並更新使用者介面。目前是透過輪詢 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 變更的方式稍有不同。喚醒服務工作者可能會耗費大量資源,因此我們必須明確說明 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