1 引言
caches
這個 API 是針對 Request
Response
的。caches
一般結合 Service Worker
使用,因為請求級別的快取與具有頁面攔截功能的 Service Worker
最配。
本週精讀的文章是 cache-api,介紹了瀏覽器快取介面的基本語法。
2 概述
瀏覽器擁有全域性變數 caches
操作快取。
caches
包含任意名稱空間,可以通過 caches.open
建立或訪問。
const myCache = await caches.open("myCache");
複製程式碼
新增快取
通過 add
新增快取。由於 caches
快取是基於請求的,因此引數可以是一個 URL 地址,或一個完整的 Request 物件:
// URL only
myCache.add("/subscribe");
// Full request object
myCache.add(new Request('/subscribe', {
method: "GET",
headers: new Headers({
'Content-Type': 'text/html'
}),
/* more request options */
});
複製程式碼
每執行 add
時,瀏覽器都會主動請求並快取返回的 Response。
可以通過 addAll
批量新增快取:
myCache.addAll(["/subscribe", "/assets/images/profile.png"]);
複製程式碼
讀取快取
通過 match
讀取快取。與 add
類似,引數可以是 URL 地址或完整 Request 物件,同時支援 matchAll
:
const res = await myCache.match("/subscribe");
複製程式碼
更新快取
通過 add
或 put
更新快取。
當某個請求快取需要更新時,你可以重新執行 add
操作。
同時 put
也可以更新快取,你可以手動構造返回值,這樣瀏覽器就不需要發請求了:
const request = new Request("/subscribe");
const fetchResponse = await fetch(request);
myCache.put(request, fetchResponse);
複製程式碼
銷燬快取
通過 delete
銷燬快取。
你可以銷燬某個路徑的快取:
myCache.delete("/subscribe");
複製程式碼
也可以銷燬某個快取名稱空間:
caches.delete("myCache");
複製程式碼
結合 service Worker
可以利用 addEventListener('fetch')
監聽瀏覽器請求時機,並在匹配到快取時,直接替換為返回結果,當快取不存在時才繼續發請求。
self.addEventListener("fetch", (e) => {
e.respondWith(
// Check if item exists in cache
caches.match(e.request).then((cachedResponse) => {
// If found in cache, return cached response
if (cachedResponse) return cachedResponse;
// If not found, fetch over network
return fetch(e.request);
});
);
});
複製程式碼
3 精讀
筆者利用 caches
API + service worker 實現了純瀏覽器端的後端渲染。
首先基於下面三個基本事實:
- 利用 service worker 可以攔截請求。
- caches 可以主動
put
修改快取。 react-dom/server
可以在瀏覽器端執行。
這三個能力組合一下,我們真的可以實現前端 SSR:
- 開啟頁面時,利用 web worker 呼叫
react-dom/server
構造一個 SSR 字串。 - 利用
caches.put
新增當前頁面快取,將react-root
部分塞入構造好的 SSR 字串。 - 下次開啟頁面時,優先命中快取,彷彿是後端提供了 SSR 服務,但其實服務是由上一次瀏覽器提供的。
前端渲染有幾個好處:
- 不消耗伺服器計算資源,如果頁面有百萬 UV,可能一天就能節省幾十萬元伺服器電費。
- 不消耗伺服器儲存資源,如果頁面是千人千面的,後端 SSR 儲存成本巨大,但分攤到個人電腦就不成問題。
- 不需要寫兩套程式碼。雖然服務端渲染重複利用前端資源,但 DOM 環境等都是模擬出來的,且前端程式碼還存在記憶體洩露風險,許多 SSR 的前端程式碼必須判斷前後端環境,給維護造成了巨大負擔。在前端渲染下這不成問題,我們的口號是:前端程式碼請交給瀏覽器執行。
筆者將這套前端渲染能力封裝在 前端工程化工具 Pri 中,開啟配置項
useServiceWorker=true
clientServerRender=true
嘗試。
後面有機會單獨選一篇精讀介紹 前端渲染,你也可以直接參考筆者 簡陋的實現:由於 service worker 必須存在一個實體檔案,因此腳手架會自動生成它,所以你看到的執行程式碼是一堆字串。
4 總結
前端渲染是一個較為極端的例子,caches
更多用來快取簡單的靜態頁面,靜態博文,或者不經常變動的後端介面。
留下一個思考題:你還能想到 caches
的其他用法嗎?歡迎留言。
如果你想參與討論,請點選這裡,每週都有新的主題,週末或週一釋出。前端精讀 - 幫你篩選靠譜的內容。