用一張圖總結web緩存策略

圖片描述

1 瀏覽器緩存

瀏覽器緩存機制有四個方面,它們按照獲取資源時請求的優先級依次排列以下:前端

1.Memory Cache數據庫

2.Service Worker Cache瀏覽器

3.HTTP Cache緩存

4.Push Cache性能優化

1.1 Memory Cache

MemoryCache,是指存在內存中的緩存。從優先級上來講,它是瀏覽器最早嘗試去命中的一種緩存。從效率上來講,它是響應速度最快的一種緩存。服務器

不過當頁面關閉時,內存裏的數據也就沒有了。網絡

資源存不存內存,瀏覽器秉承的是「節約原則」。咱們發現,Base64 格式的圖片,幾乎永遠能夠被塞進 memory cache,這能夠視做瀏覽器爲節省渲染開銷的「自保行爲」;此外,體積不大的 JS、CSS 文件,也有較大地被寫入內存的概率——相比之下,較大的 JS、CSS 文件就沒有這個待遇了,內存資源是有限的,它們每每被直接甩進磁盤。session

1.2 Service Worker Cache

Service Worker 是一種獨立於主線程以外的 Javascript 線程。它能夠幫咱們實現離線緩存、消息推送和網絡代理等功能。前端性能

一般咱們若是要使用 Service Worker 基本就是如下幾個步驟:性能

  • 首先咱們須要在頁面的 JavaScript 主線程中註冊 Service Worker。
  • 註冊成功後後臺開始安裝步驟, 一般在安裝的過程當中須要緩存一些靜態資源。
  • 安裝成功後開始激活 Service Worker
  • 激活成功後 Service Worker 能夠控制頁面了(監聽 fetch 和 message 事件),可是隻針對在成功註冊了 Service Worker 後打開的頁面。

在頁面發起 http 請求時,service worker 能夠經過 fetch 事件攔截請求,而且給出本身的響應。

頁面和 serviceWorker 之間能夠經過 posetMessage() 方法發送消息,發送的消息能夠經過 message 事件接收到。

Service Worker 必須以 https 協議爲前提。

1.3 HTTP 緩存

HTTP 緩存分爲強緩存和協商緩存。優先級較高的是強緩存,在命中強緩存失敗的狀況下,纔會走協商緩存。

1.3.1 強緩存

強緩存指的是向瀏覽器緩存查找該請求的結果,並根據該結果的緩存規則來決定是否使用該緩存結果的過程

強緩存是利用http響應頭中的 ExpiresCache-Control 兩個字段來控制的。

1.3.1.1 Expires

實現強緩存,過去咱們一直用 expires

在服務器的響應頭裏,會將過時時間寫入 expires 字段:

圖片描述

那麼,當咱們試圖再次向服務器請求資源時,瀏覽器就會先對比本地時間和 expires 的時間,若是本地時間小於 expires 設定的過時時間,就直接去緩存中取這個資源。

不過expires依賴於本地時間,若是服務端和客戶端的時間設置不一樣,那麼expires 將沒法達到咱們的預期。

1.3.1.2 Cache-Control

考慮到 expires 的侷限性,HTTP1.1 新增了 Cache-Control 字段來完成 expires 的任務。當 Cache-Control 與 expires 同時出現時,咱們以 Cache-Control 爲準。

Cache-Control 包含如下幾個值:

(1)max-age

cache-control: max-age=31536000

max-age 會等於一個時間長度(以秒爲單位)。在本例中,max-age 是 31536000 秒,它意味着該資源在 31536000 秒之內都是有效的,完美地規避了時間戳帶來的潛在問題。

在代理服務器中,咱們使用 s-maxage 來執行 max-age 的功能。

(2)public 與 private

若是咱們爲資源設置了 public,那麼它既能夠被瀏覽器緩存,也能夠被代理服務器緩存(也就是多個用戶能夠共享這個緩存);若是咱們設置了 private,則該資源只能被瀏覽器緩存。

private 爲默認值。

但多數狀況下,public 並不須要咱們手動設置,由於設置了 max-age 就表示響應是能夠緩存的。

(3)no-store 與 no-cache

若是咱們爲資源設置了 no-cache,瀏覽器會對響應進行緩存,可是須要到服務器去確認這個緩存是否能用。即走咱們下文即將講解的協商緩存的路線。

若是設置了 no-store ,全部內容都不會被緩存,即不使用強制緩存,也不使用協商緩存

1.3.2 協商緩存

協商緩存指的是強制緩存失效後,瀏覽器向服務器詢問緩存的相關信息,進而判斷是從新發起請求仍是從本地拿緩存的過程。

若是服務端提示緩存資源未改動(Not Modified),資源會被重定向到瀏覽器緩存,這種狀況下網絡請求對應的狀態碼是 304(以下圖)。

圖片描述

一樣,協商緩存的標識也是在響應報文的HTTP頭中和請求結果一塊兒返回給瀏覽器的,控制協商緩存的字段分別有:Last-Modified / If-Modified-Since和Etag / If-None-Match,其中Etag / If-None-Match的優先級比Last-Modified / If-Modified-Since高。

1.3.2.1 Last-Modified / If-Modified-Since

若是咱們啓用了協商緩存,Last-Modified 會在首次請求時隨着響應頭返回:

Last-Modified: Fri, 27 Oct 2017 06:35:57 GMT

隨後咱們每次請求時,會帶上一個叫 If-Modified-Since 的時間戳字段,它的值正是上一次 response 返回給它的 last-modified 值:

If-Modified-Since: Fri, 27 Oct 2017 06:35:57 GMT

服務器接收到這個時間戳後,會比對該時間戳和資源在服務器上的最後修改時間是否一致,從而判斷資源是否發生了變化。若是發生了變化,就會返回一個完整的響應內容,並在響應頭中添加新的 Last-Modified 值;不然,返回如上圖的 304 響應,響應頭不會再添加 Last-Modified 字段。

1.3.2.2 Etag / If-None-Match

Etag 是由服務器爲每一個資源生成的惟一的標識字符串,這個標識字符串是基於文件內容編碼的,只要文件內容不一樣,它們對應的 Etag 就是不一樣的。

當首次請求時,咱們會在響應頭裏獲取到一個最初的標識符字符串:

ETag: W/"2a3b-1602480f459"

那麼下一次請求時,請求頭裏就會帶上一個值相同的、名爲 if-None-Match 的字符串供服務端比對:

If-None-Match: W/"2a3b-1602480f459"

不過 Etag 的生成過程須要服務器額外付出開銷,會影響服務端的性能。

1.3.3 HTTP 緩存決策指南

根據上文所說的 HTTP 緩存知識點,咱們在面對一個具體的緩存需求時,能夠根據下圖的路線來決策:

圖片描述

當咱們的資源內容不可複用時,直接爲 Cache-Control 設置 no-store,拒絕一切形式的緩存;不然考慮是否每次都須要向服務器進行緩存有效確認,若是須要,那麼設 Cache-Control 的值爲 no-cache;不然考慮該資源是否能夠被代理服務器緩存,根據其結果決定是設置爲 private 仍是 public;而後考慮該資源的過時時間,設置對應的 max-age 和 s-maxage 值;最後,配置協商緩存須要用到的 Etag、Last-Modified 等參數。

1.4 Push Cache

Push Cache 是指 HTTP2 在 server push 階段存在的緩存。

2 服務器緩存

2.1 CDN

CDN (Content Delivery Network,即內容分發網絡)指的是一組分佈在各個地區的服務器。這些服務器存儲着數據的副本,所以服務器能夠根據哪些服務器與用戶距離最近,來知足數據的請求。 CDN 提供快速服務,較少受高流量影響。

CDN 的核心點有兩個,一個是緩存,一個是回源。

「緩存」就是說咱們把資源 copy 一份到 CDN 服務器上這個過程,「回源」就是說 CDN 發現本身沒有這個資源(通常是緩存的數據過時了),轉頭向根服務器(或者它的上層服務器)去要這個資源的過程。

CDN 每每被用來存放靜態資源,就是像 JS、CSS、圖片等不須要業務服務器進行計算即得的資源。

3 HTML5緩存

3.1 Web Storage

Web Storage 是 HTML5 專門爲瀏覽器存儲而提供的數據存儲機制。存儲容量能夠達到 5-10M 之間。它又分爲 Local Storage 與 Session Storage。

3.1.1 Local Storage 與 Session Storage 的區別

二者的區別在於生命週期與做用域的不一樣。

  • 生命週期:存儲在Local Storage的數據是永遠不會過時的,使其消失的惟一辦法是手動刪除;而 Session Storage 是臨時性的本地存儲,當會話結束(頁面被關閉)時,存儲內容也隨之被釋放。
  • 做用域:Local Storage、Session Storage 和 Cookie 都遵循同源策略。但 Session Storage 特別的一點在於,即使是相同域名下的兩個頁面,只要它們不在同一個瀏覽器窗口中打開,那麼它們的 Session Storage 內容便沒法共享。

3.1.2 Web Storage 核心 API 使用示例

(1)存儲數據

localStorage.setItem('user_name', 'xiuyan')

sessionStorage.setItem('key', 'value');

Web Storage只能存字符串。

(2)讀取數據

localStorage.getItem('user_name')

var data = sessionStorage.getItem('key');

(3)刪除某一鍵名對應的數據

localStorage.removeItem('user_name')

sessionStorage.removeItem('key');

(4)清除全部數據

localStorage.clear()

sessionStorage.clear();

3.1.3 應用場景

Local Storage 的特色之一是持久,有時咱們更傾向於用它來存儲一些內容穩定的資源。好比圖片內容豐富的電商網站會用它來存儲 Base64 格式的圖片字符串,有的網站還會用它存儲一些不常常更新的 CSS、JS 等靜態資源。

Session Storage 更適合用來存儲生命週期和它同步的會話級別的信息。這些信息只適用於當前會話,當你開啓新的會話時,它也須要相應的更新或釋放。好比微博的 Session Storage 就主要是存儲你本次會話的瀏覽足跡。

3.2 IndexDB

IndexDB 是一個運行在瀏覽器上的非關係型數據庫。

4 參考文章

相關文章
相關標籤/搜索