題幹與適用場景
一個離線優先網頁需要在 Service Worker 中感知登入 Cookie 變化,並更新快取策略。請設計 Cookie Store API 方案,說明訂閱範圍、事件語義、競態和不支援瀏覽器的降級。
Cookie Store API 提供非同步的 Cookie 讀取與寫入,並允許 Service Worker 訂閱匹配的 Cookie 變化。它適合取代阻塞式的 document.cookie 讀取,但不會改變 Cookie 的同源、路徑、Secure、HttpOnly 或 SameSite 約束。
面試官考察點
重點包括:區分頁面 API 與 Service Worker 的訂閱 API、理解 cookiechange 只報告腳本可見變化、按名稱和 URL 過濾、處理重複訂閱與事件競態,以及避免把 Cookie 當作可靠的跨上下文資料庫。
澄清問題
先確認 Cookie 是否 HttpOnly、作用域是否跨路徑、頁面與 Service Worker 是否同源,以及目標瀏覽器支援情況。再問登入、登出和刷新是否可能並行發生,快取更新是否必須即時,離線期間允許多長時間使用舊會話狀態。
30 秒回答框架
「我會在 Service Worker 註冊時訂閱需要的 Cookie 名稱和 URL,收到 cookiechange 後只重新讀取相關 Cookie,並讓快取策略透過單調版本或會話狀態機更新。Cookie Store API 是非同步 API,事件只涵蓋腳本可見的變化,也不提供交易或全域順序保證;因此處理器必須具備冪等性、去重並重新讀取目前狀態。對不支援的瀏覽器,我會保留網路請求中的 Cookie 驗證和頁面端明確同步,絕不把舊快取當成已登入證明。」
分步驟深入解答
第一步:明確 API 邊界
頁面可透過 window.cookieStore 非同步讀取和寫入 Cookie;Service Worker 則透過 registration.cookies 管理訂閱,並接收 cookiechange 事件。兩者都受瀏覽器 Cookie 策略約束,無法讀取 HttpOnly Cookie 的值。
第二步:按最小範圍建立訂閱
訂閱應指定必要的 Cookie 名稱,並在確實需要時限定 URL。同名但路徑不同的 Cookie 可能同時存在,處理器必須依據事件中的變更資訊和目前 URL 重新確認目標,而不是只按名稱猜測。
self.addEventListener("activate", (event) => {
event.waitUntil(
self.registration.cookies.subscribe([
{ name: "session", url: self.registration.scope },
]),
);
});第三步:理解事件不是值快照
事件包含變化的 Cookie 集合,但非同步處理時 Cookie 可能已再次變化。收到事件後應重新呼叫 get() 或 getAll() 讀取目前狀態,並讓處理器具備冪等性;不要把事件物件當作交易日誌或最終真相。
第四步:區分腳本可見與 HttpOnly 變化
規範只要求腳本可見的 Cookie 變化觸發相關通知。伺服器設定或刪除 HttpOnly Cookie 後,Service Worker 不能讀取其值,也不應從缺少通知推斷會話沒有變化。認證結論仍需由伺服器回應決定。
第五步:建立會話狀態機
把狀態定義為未知、已驗證、已登出或過期,並使用回應中的版本、過期時間或重新驗證結果推進狀態。Cookie 變化只觸發重新檢查,不直接等同於登入成功或登出完成。
第六步:處理並行與跨分頁競態
多個頁面可能同時刷新或刪除 Cookie。處理器應合併短時間內的通知,按目前讀取結果執行一次快取更新,並用會話版本避免舊事件覆蓋新狀態。快取刪除與預快取寫入也應具備冪等性。
第七步:設計不支援瀏覽器的降級
如果瀏覽器沒有 Cookie Store API,頁面可以在關鍵導覽或網路回應後明確發送同步訊號,伺服器仍以 Cookie 驗證為準。不要透過輪詢 document.cookie 讀取 HttpOnly 值,也不要因為 API 缺失就放寬快取認證條件。
第八步:限制隱私和安全暴露
訂閱只涵蓋業務需要的名稱與 URL,避免將 Cookie 值寫入日誌、Cache Storage 或 postMessage。設定 Cookie 時繼續使用 Secure、HttpOnly、SameSite、Path 和合理的過期時間,並在登出時同時清理客戶端快取。
高品質示例答案
我會把 Cookie Store API 當作變化提示器,而不是認證資料庫。Service Worker 啟用時,為特定名稱和作用域建立訂閱;收到 cookiechange 後重新讀取目前腳本可見狀態,進入具冪等性的會話狀態機,並透過會話版本更新或清理快取。HttpOnly Cookie 的值始終由伺服器回應驗證,事件缺失也不代表會話沒有變化。多個頁面同時刷新時合併通知,避免舊事件覆蓋新狀態。對不支援的瀏覽器,保留關鍵請求的伺服器驗證與頁面端明確同步,不能用 document.cookie 輪詢取代 HttpOnly 保護。所有訂閱和快取操作都限制作用域,並覆蓋登出、過期、離線和 Service Worker 更新場景。
常見誤區
把 cookiechange 當成完整稽核日誌
事件是通知,不提供跨程序交易序列。處理器必須重新讀取目前狀態並支援重複執行。
認為 Service Worker 能讀取 HttpOnly Cookie
HttpOnly 仍禁止腳本讀取。Service Worker 只能透過網路請求讓伺服器驗證會話,不能從 Cookie Store API 取得秘密值。
用 Cookie 變化直接決定快取認證
Cookie 變化可能來自刷新、過期或不同路徑。快取策略應等待伺服器驗證和版本狀態,不能把任意變化當作登入或登出結論。
延伸追問與參考答案
同名 Cookie 位於不同 Path 時如何避免誤刪?
在訂閱和讀取時保留 URL 作用域,刪除時使用精確的 name、URL、Path 與其他屬性。若無法確認目標 Cookie,就讓伺服器透過回應完成清理,不發送寬泛刪除操作。
Service Worker 更新期間訂閱會不會遺失?
在新的 Worker 的 activate 階段冪等地確保訂閱存在,並在遷移時讀取目前 Cookie 狀態重建快取。不要依賴舊 Worker 的記憶體狀態;更新完成後重新執行初始化。
離線時 Cookie 過期但沒有網路,快取該怎麼辦?
把本地狀態標記為待驗證並限制離線能力,不能延長伺服器會話。恢復網路後先執行認證請求,再決定恢復、清理或降級快取。