精讀《Caches API》

1 引言

caches 這個 API 是針對 Request Response 的。caches 通常結合 Service Worker 使用,由於請求級別的緩存與具備頁面攔截功能的 Service Worker 最配。html

本週精讀的文章是 cache-api,介紹了瀏覽器緩存接口的基本語法。前端

2 概述

瀏覽器擁有全局變量 caches 操做緩存。react

caches 包含任意命名空間,能夠經過 caches.open 建立或訪問。git

const myCache = await caches.open("myCache");

添加緩存

經過 add 添加緩存。因爲 caches 緩存是基於請求的,所以參數能夠是一個 URL 地址,或一個完整的 Request 對象:github

// 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。web

能夠經過 addAll 批量添加緩存:typescript

myCache.addAll(["/subscribe", "/assets/images/profile.png"]);

讀取緩存

經過 match 讀取緩存。與 add 相似,參數能夠是 URL 地址或完整 Request 對象,同時支持 matchAll後端

const res = await myCache.match("/subscribe");

更新緩存

經過 addput 更新緩存。前端工程化

當某個請求緩存須要更新時,你能夠從新執行 add 操做。api

同時 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:

  1. 打開頁面時,利用 web worker 調用 react-dom/server 構造一個 SSR 字符串。
  2. 利用 caches.put 添加當前頁面緩存,將 react-root 部分塞入構造好的 SSR 字符串。
  3. 下次打開頁面時,優先命中緩存,彷彿是後端提供了 SSR 服務,但其實服務是由上一次瀏覽器提供的。

前端渲染有幾個好處:

  1. 不消耗服務器計算資源,若是頁面有百萬 UV,可能一天就能節省幾十萬元服務器電費。
  2. 不消耗服務器存儲資源,若是頁面是千人千面的,後端 SSR 存儲成本巨大,但分攤到我的電腦就不成問題。
  3. 不須要寫兩套代碼。雖然服務端渲染重複利用前端資源,但 DOM 環境等都是模擬出來的,且前端代碼還存在內存泄露風險,許多 SSR 的前端代碼必須判斷先後端環境,給維護形成了巨大負擔。在前端渲染下這不成問題,咱們的口號是:前端代碼請交給瀏覽器執行。
筆者將這套前端渲染能力封裝在 前端工程化工具 Pri 中,開啓配置項 useServiceWorker=true clientServerRender=true 嘗試。

後面有機會單獨選一篇精讀介紹 前端渲染,你也能夠直接參考筆者 簡陋的實現:因爲 service worker 必須存在一個實體文件,所以腳手架會自動生成它,因此你看到的運行代碼是一堆字符串。

4 總結

前端渲染是一個較爲極端的例子,caches 更多用來緩存簡單的靜態頁面,靜態博文,或者不常常變更的後端接口。

留下一個思考題:你還能想到 caches 的其餘用法嗎?歡迎留言。

討論地址是: 精讀《Caches API》 · Issue #124 · dt-fe/weekly

若是你想參與討論,請點擊這裏,每週都有新的主題,週末或週一發佈。前端精讀 - 幫你篩選靠譜的內容。

相關文章
相關標籤/搜索