參閱了一些瀏覽器緩存的資料,本文經過一張圖來概括總結其過程。html
瀏覽器第一次向一個web服務器發起http
請求後,服務器會返回請求的資源,而且在響應頭中添加一些有關緩存的字段如:Cache-Control
、Expires
、Last-Modified
、ETag
、Date
等等。以後瀏覽器再向該服務器請求該資源就能夠視狀況使用強緩存和協商緩存。web
下面假定瀏覽器已經訪問了服務器,服務器返回了緩存相關的頭部字段且瀏覽器已對相關資源作好緩存。經過下圖來分析強緩存和協商緩存:瀏覽器
如圖紅線所示的過程表明強緩存。用戶發起了一個http
請求後,瀏覽器發現先本地已有所請求資源的緩存,便開始檢查緩存是否過時。有兩個http頭部字段控制緩存的有效期:Expires
和Cache-Control
,瀏覽器是根據如下兩步來斷定緩存是否過時的:緩存
Cache-Control
的s-maxage
或max-age
指令,如有,則使用響應報文生成時間Date + s-maxage/max-age
得到過時時間,再與當前時間進行對比(s-maxage
適用於多用戶使用的公共緩存服務器);Cache-Control
的s-maxage
或max-age
指令,則比較Expires
中的過時時間與當前時間。Expires
是一個絕對時間。注意,在HTTP/1.1中,當首部字段Cache-Control
有指定s-maxage
或max-age
指令,比起首部字段Expires
,會優先處理s-maxage
或max-age
。服務器
另外下面列幾個Cache-Control
的經常使用指令:spa
no-cache
:含義是不使用本地緩存,須要使用協商緩存,也就是先與服務器確認緩存是否可用。no-store
:禁用緩存。public
:代表其餘用戶也可以使用緩存,適用於公共緩存服務器的狀況。private
:代表只有特定用戶才能使用緩存,適用於公共緩存服務器的狀況。通過上述兩步判斷後,若緩存未過時,返回狀態碼爲200
,則直接從本地讀取緩存,這就完成了整個強緩存過程;若是緩存過時,則進入協商緩存或服務器返回新資源過程。code
當瀏覽器發現緩存過時後,緩存並不必定不能使用了,由於服務器端的資源可能仍然沒有改變,因此須要與服務器協商,讓服務器判斷本地緩存是否還能使用。此時瀏覽器會判斷緩存中是否有ETag
或Last-Modified
字段,若是沒有,則發起一個http請求,服務器根據請求返回資源;若是有這兩個字段,則在請求頭中添加If-None-Match
字段(有ETag
字段的話添加)、If-Modified-Since
字段(有Last-Modified
字段的話添加)。注意:若是同時發送If-None-Match
、If-Modified-Since
字段,服務器只要比較If-None-Match
和ETag
的內容是否一致便可;若是內容一致,服務器認爲緩存仍然可用,則返回狀態碼304
,瀏覽器直接讀取本地緩存,這就完成了協商緩存的過程,也就是圖中的藍線;若是內容不一致,則視狀況返回其餘狀態碼,並返回所請求資源。下面詳細解釋下這個過程:htm
ETag
和If-None-Match
兩者的值都是服務器爲每份資源分配的惟一標識字符串。blog
ETag
字段。資源更新時,服務器端的ETag
值也隨之更新;If-None-Match
字段,它的值就是上次響應報文中的ETag
的值;ETag
與If-None-Match
的值是否一致,若是不一致,服務器則接受請求,返回更新後的資源;若是一致,代表資源未更新,則返回狀態碼爲304
的響應,可繼續使用本地緩存,要注意的是,此時響應頭會加上ETag
字段,即便它沒有變化。Last-Modified
和If-Modified-Since
兩者的值都是GMT格式的時間字符串。ip
Last-Modified
字段,代表該資源最後一次的修改時間;If-Modified-Since
字段,它的值就是上次服務器響應報文中的Last-Modified
的值;Last-Modified
與If-Modified-Since
的值是否一致,若是不一致,服務器則接受請求,返回更新後的資源;若是一致,代表資源未更新,則返回狀態碼爲304
的響應,可繼續使用本地緩存,與ETag
不一樣的是:此時響應頭中不會再添加Last-Modified
字段。ETag
較之Last-Modified
的優點如下內容引用於:http協商緩存VS強緩存
你可能會以爲使用Last-Modified
已經足以讓瀏覽器知道本地的緩存副本是否足夠新,爲何還須要ETag
呢?HTTP1.1
中ETag
的出現主要是爲了解決幾個Last-Modified
比較難解決的問題:
GET
;If-Modified-Since
能檢查到的粒度是s級的,這種修改沒法判斷(或者說UNIX
記錄MTIME
只能精確到秒);這時,利用ETag
可以更加準確的控制緩存,由於ETag
是服務器自動生成的資源在服務器端的惟一標識符,資源每次變更,都會生成新的ETag
值。Last-Modified
與ETag
是能夠一塊兒使用的,但服務器會優先驗證ETag
。
最後附一張圖說明用戶行爲對瀏覽器緩存的影響: