透過瀏覽器看 HTTP 緩存

作爲前端開發人員,對於我們的站點或應用的緩存機制我們能做的似乎不多,但這些卻是與我們關注的性能息息相關的部分,站點沒有做任何緩存機制,我們的頁面可能會因爲資源的下載和渲染變得很慢,但大家都知道去找前端去解決頁面慢的問題而不會去找服務端的開發人員。因此,瞭解相關的緩存機制和充分的利用它似乎就變得必不可少。 

web 端的緩存機制其實有多種,我在這裏只是學習和整理了以瀏覽器爲載體的 HTTP 緩存機制,看看它是如何工作的。

一、web 緩存的種類

1.1 數據庫緩存

我們可能聽說過 memcached,它就是一種數據庫層面的緩存方案。數據庫緩存是指,當 web 應用的關係比較複雜,數據庫中的表很多的時候,如果頻繁進行數據庫查詢,很容易導致數據庫不堪重荷。爲了提供查詢的性能,將查詢後的數據放到內存中進行緩存,下次查詢時,直接從內存緩存直接返回,提供響應效率。

1.2 CDN 緩存

CDN 緩存一般是由網站管理員自己部署,爲了讓他們的網站更容易擴展並獲得更好的性能。通常情況下,瀏覽器先向 CDN 網關發起 Web 請求,網關服務器後面對應着一臺或多臺負載均衡源服務器,會根據它們的負載請求,動態將請求轉發到合適的源服務器上。從瀏覽器角度來看,整個 CDN 就是一個源服務器,從這個層面來說,瀏覽器和服務器之間的緩存機制,在這種架構下同樣適用。

1.3 代理服務器緩存

代理服務器是瀏覽器和源服務器之間的中間服務器,瀏覽器先向這個中間服務器發起 Web 請求,經過處理後(比如權限驗證,緩存匹配等),再將請求轉發到源服務器。代理服務器緩存的運作原理跟瀏覽器的運作原理差不多,只是規模更大。

1.4 瀏覽器緩存

每個瀏覽器都實現了 HTTP 緩存,我們通過瀏覽器使用 HTTP 協議與服務器交互的時候,瀏覽器就會根據一套與服務器約定的規則進行緩存工作。

1.5 應用層緩存

應用層緩存是指我們在代碼層面上做的緩存。通過代碼邏輯,把曾經請求過的數據或資源等,緩存起來,再次需要數據時通過邏輯上的處理選擇可用的緩存的數據。

二、爲什麼需要瀏覽器緩存?我們需要做些什麼?

我們知道通過 HTTP 協議,在客戶端和瀏覽器建立連接時需要消耗時間,而大的響應需要在客戶端和服務器之間進行多次往返通信才能獲得完整的響應,這拖延了瀏覽器可以使用和處理內容的時間。這就增加了訪問服務器的數據和資源的成本,因此利用瀏覽器的緩存機制重用以前獲取的數據就變成了性能優化時需要考慮的事情。

那麼有什麼建議嗎?當然。

爲每個資源指定一個明確的緩存策略,用以定義資源是否可以緩存,由誰來緩存,可以緩存多久,並且在緩存時間到期時如何有效地重新驗證。當服務器返回一個響應時,它需要在響應頭中提供 Cache-Control 和 ETag。

說到瀏覽器中的緩存機制,其實就相當於 HTTP 協議定義的緩存機制,因爲瀏覽器爲我們實現了它。一般情況下我們會想到到 HTTP 響應頭中的 Expires,Cache-Control,Last-Modified.If-Modified-Since,Etag 這樣的與緩存相關的響應頭信息。

但是這裏我們說服務器返回一個響應時提供必要的 Cache-Control 和 Etag 即可。這是爲什麼呢?

因爲 Cache-Control 與 Expires 的作用一致,Last-Modified 與 ETag 的作用也相近。但它們有以下區別:

       

現在默認瀏覽器均默認使用 HTTP 1.1,所以 Expires 和 Last-Modified 的作用基本可以忽略,具備 Cache-Control 和 Etag 即可。

當然用戶的行爲也會影響瀏覽器的緩存,像這樣:

但我們先不考慮用戶的操作的影響,來看看服務器提供 Cache-Control 和 ETag 響應頭來進行的緩存是如何工作的。

三、使用 Etag 驗證緩存的 HTTP 響應

通常情況下,請求一個資源的過程大概是這樣的:

      

這裏就看下 Etag 的作用。

3.1 Etag 的主要作用

服務器通過 ETag HTTP 頭傳遞驗證碼,大概是像‘‘x123cef’’這樣的字符串。當瀏覽器在資源過期後再次請求時,瀏覽器默認會通過 If-None-Match 傳遞 Etag 的驗證碼,通過驗證碼可以進行高效的資源更新檢查:如果資源未更改,則不會傳輸任何數據。

Etag 就主要用來在響應過期之後,驗證資源是否被修改。

3.2 Etag 的工作原理

如上圖,服務器在第一次返回響應的時候設置了緩存的時間 120s,假設瀏覽器在這 120s 經過之後再次請求服務器相同的資源,首先,瀏覽器會檢查本地緩存並找到之前的響應,不幸的是,這個響應現在已經’過期’,無法在使用。此時,瀏覽器也可以直接發出新請求,獲取新的完整響應,但是這樣做效率較低,因爲如果資源未被更改過,我們就沒有理由再去下載與緩存中已有的完全相同的字節。

於是就到了 Etag 發揮作用的時候了,通常服務器生成並返回在 Etag 中的驗證碼,常常是文件內容的哈希值或者某個其他指紋碼。客戶端不必瞭解指紋碼是如何生成的,只需要在下一個請求中將其發送給服務器 (瀏覽器默認會添加):如果指紋碼仍然一致,說明資源未被修改,服務器會反悔 304 Not Modified,這樣我們就可以跳過下載,利用已經緩存了的資源,並且該資源會繼續緩存 120s。就像這樣:

四、什麼是 Cache-Control?如何定義 Cache-Control?

服務器響應瀏覽器請求時響應頭中的 Cache-Control 響應頭使得每個資源都可以通過 Cache-Control HTTP 頭來定義自己的緩存策略,Cache-Control 指令用來告訴我們,那個資源在什麼條件下可以緩存,以及可以緩存多久。

4.1 Cache-Control 頭參數的含義 (響應頭中的 Cache-Control)

  1. no-cache : 表示必須先與服務器確認返回的響應是否被更改,然後才能使用該響應來滿足後續對同一個網址的請求。因此,如果存在合適的驗證令牌 (ETag),no-cache 會發起往返通信來驗證緩存的響應,如果資源未被更改,可以避免下載。

  2. no-store : 禁止緩存任何響應,也就是說每次用戶請求資源時,都會向服務器發送一個請求,每次都會下載完整的響應。

  3. public :如果響應被標記爲 public,即使有關聯的 HTTP 認證,甚至響應狀態碼無法正常緩存,響應也可以被緩存。

  4. private : 瀏覽器可以緩存 private 響應,但是通常只爲單個用戶緩存,因此,不允許任何代理服務器對其進行緩存 。比如,用戶瀏覽器可以緩存包含用戶私人信息的 HTML 網頁,但是 CDN 不能緩存。

  5. max-age :  用來設置資源被緩存的最長時間 (單位是秒)。

4.2 如何使用 Cache-Control

通常,我們可以通過下圖的流程來設置合適的響應頭的 Cache-Control 頭。

五、已經緩存的響應,如何更新或廢棄?

一般情況下,瀏覽器發出的所有 HTTP 請求會首先被路由到瀏覽器的緩存,以查看是否緩存了可以用於實現請求的有效響應。如果有匹配的響應,會直接從緩存中讀取響應,這樣就避免了網絡延遲以及傳輸產生的數據成本。然而,如果我們希望更新或廢棄已緩存的響應,該怎麼辦?

假設我們已經告訴訪問者某個 CSS 樣式表緩存長達 24 小時 (max-age=86400),但是設計人員剛剛提交了一個更新,我們希望所有用戶都能使用。我們該如何通知所有訪問者緩存的 CSS 副本已過時,需要更新緩存? 

實際上以前沒有請求過該資源的新的用戶會得到更新的資源,但是請求過資源的用戶將在過期時間達到之前一直得到舊的被緩存的資源,直到他手動的去清理了瀏覽器的緩存。手動清理瀏覽器緩存這種事可能只有程序員纔會做,那麼我們要怎麼做才能讓用戶得到更新後的資源呢?

其實很簡單,我們可以在資源的內容更改後,更改資源的網址,強制用戶下載新響應。比如在資源鏈接後添加參數:

六、對於緩存機制,現在可以做的有哪些?

我在瀏覽資料的時候發現了一個 caching checklist,比較具有參考價值,我們可以遵循建議合理的利用緩存機制:

  1. 使用一致的網址:如果在不同的網址上提供相同的內容,那麼將會多次獲取和存儲相同的內容。提示:網址是區分大小寫的!

  2. 確保服務器提供驗證碼 (ETag):通過驗證碼,如果服務器上的資源未被更改,就不必傳輸相同的字節。

  3. 確定代理緩存可以緩存哪些資源:對所有用戶的響應完全相同的資源很適合由 CDN 或其他代理緩存進行緩存。

  4. 確定每個資源的最優緩存週期:不同的資源可能有不同的更新要求。審查並確定每個資源適合的 max-age。

  5. 確定網站的最佳緩存層級:對 HTML 文檔組合使用包含內容指紋碼的資源網址以及短時間或 no-cache 的生命週期,可以控制客戶端獲取更新的速度。

  6. 變動最小化:有些資源的更新比其他資源頻繁。如果資源的特定部分(例如 JavaScript 函數或一組 CSS 樣式)會經常更新,應考慮將其代碼作爲單獨的文件提供。這樣,每次獲取更新時,剩餘內容(例如不會頻繁更新的庫代碼)可以從緩存中獲取,確保下載的內容量最少。

作者:@大額大額哼歌等日落

來源:http://www.cnblogs.com/skylar/p/browser-http-caching.html

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/mxfyvb4_TPq8dLPn24x_3g