一、概述
良好的緩存策略可以降低資源的重復加載提高網(wǎng)頁的整體加載速度
通常瀏覽器緩存策略分為兩種:強緩存和協(xié)商緩存
1厉亏、基本原理
- 1)瀏覽器在加載資源時董习,根據(jù)請求頭的
expires
和cache-control
判斷是否命中強緩存,是則直接從緩存讀取資源爱只,不會發(fā)請求到服務器皿淋。 - 2)如果沒有命中強緩存,瀏覽器一定會發(fā)送一個請求到服務器恬试,通過
last-modified
和etag
驗證資源是否命中協(xié)商緩存窝趣,如果命中,服務器會將這個請求返回训柴,但是不會返回這個資源的數(shù)據(jù)哑舒,依然是從緩存中讀取資源 - 3)如果前面兩者都沒有命中,直接從服務器加載資源
2畦粮、相同點
如果命中散址,都是從客戶端緩存中加載資源,而不是從服務器加載資源數(shù)據(jù)宣赔;
3预麸、不同點
強緩存不發(fā)請求到服務器,協(xié)商緩存會發(fā)請求到服務器儒将。
二吏祸、強緩存
強緩存通過Expires
和Cache-Control
兩種響應頭實現(xiàn)
1、Expires
Expires是http1.0提出的一個表示資源過期時間的header钩蚊,它描述的是一個絕對時間贡翘,由服務器返回蹈矮。
Expires 受限于本地時間,如果修改了本地時間鸣驱,可能會造成緩存失效
Expires: Wed, 11 May 2018 07:20:00 GMT
2泛鸟、Cache-Control
Cache-Control 出現(xiàn)于 HTTP / 1.1,優(yōu)先級高于 Expires ,表示的是相對時間
Cache-Control: max-age=315360000
題外tips
Cache-Control: no-cache
不會緩存數(shù)據(jù)到本地的說法是錯誤的踊东,詳情《HTTP權威指南》P182
Cache-Control: no-store
才是真正的不緩存數(shù)據(jù)到本地
Cache-Control: public
可以被所有用戶緩存(多用戶共享)北滥,包括終端和CDN等中間代理服務器
Cache-Control: private
只能被終端瀏覽器緩存(而且是私有緩存),不允許中繼緩存服務器進行緩存
三闸翅、協(xié)商緩存
當瀏覽器對某個資源的請求沒有命中強緩存再芋,就會發(fā)一個請求到服務器,驗證協(xié)商緩存是否命中坚冀,如果協(xié)商緩存命中济赎,請求響應返回的http狀態(tài)為304并且會顯示一個Not Modified的字符串
協(xié)商緩存是利用的是【Last-Modified,If-Modified-Since】
和【ETag记某、If-None-Match】
這兩對Header來管理的
1司训、Last-Modified,If-Modified-Since
Last-Modified
表示本地文件最后修改日期辙纬,瀏覽器會在request header加上If-Modified-Since
(上次返回的Last-Modified
的值)豁遭,詢問服務器在該日期后資源是否有更新叭喜,有更新的話就會將新的資源發(fā)送回來
但是如果在本地打開緩存文件贺拣,就會造成 Last-Modified 被修改,所以在 HTTP / 1.1 出現(xiàn)了 ETag
2捂蕴、ETag譬涡、If-None-Match
Etag
就像一個指紋,資源變化都會導致ETag變化啥辨,跟最后修改時間沒有關系涡匀,ETag
可以保證每一個資源是唯一的
If-None-Match
的header會將上次返回的Etag
發(fā)送給服務器,詢問該資源的Etag
是否有更新溉知,有變動就會發(fā)送新的資源回來
ETag
的優(yōu)先級比Last-Modified
更高
具體為什么要用ETag
陨瘩,主要出于下面幾種情況考慮:
- 一些文件也許會周期性的更改,但是他的內(nèi)容并不改變(僅僅改變的修改時間)级乍,這個時候我們并不希望客戶端認為這個文件被修改了舌劳,而重新GET;
- 某些文件修改非常頻繁玫荣,比如在秒以下的時間內(nèi)進行修改甚淡,(比方說1s內(nèi)修改了N次),If-Modified-Since能檢查到的粒度是s級的捅厂,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒)贯卦;
- 某些服務器不能精確的得到文件的最后修改時間资柔。
四、整體流程圖
五撵割、幾種狀態(tài)碼的區(qū)別
-
200
:強緩Expires/Cache-Control存失效時贿堰,返回新的資源文件 -
200(from cache)
: 強緩Expires/Cache-Control兩者都存在,未過期啡彬,Cache-Control優(yōu)先Expires時官边,瀏覽器從本地獲取資源成功 -
304(Not Modified )
:協(xié)商緩存Last-modified/Etag沒有過期時,服務端返回狀態(tài)碼304
但是外遇!但是注簿!
現(xiàn)在的200(from cache)
已經(jīng)變成了from disk cache(磁盤緩存)
和from memory cache(內(nèi)存緩存)
兩種
打開chrome控制臺看一下網(wǎng)絡請求就知道了
具體兩者的區(qū)別,暫時沒有去深究跳仿,有興趣的同學可以自己去研究
六诡渴、如何選擇合適的緩存
大致的順序
- Cache-Control —— 請求服務器之前
- Expires —— 請求服務器之前
- If-None-Match (Etag) —— 請求服務器
- If-Modified-Since (Last-Modified) —— 請求服務器
協(xié)商緩存需要配合強緩存使用,如果不啟用強緩存的話菲语,協(xié)商緩存根本沒有意義
大部分web服務器都默認開啟協(xié)商緩存妄辩,而且是同時啟用【Last-Modified,If-Modified-Since】和【ETag山上、If-None-Match】
但是下面的場景需要注意:
- 分布式系統(tǒng)里多臺機器間文件的Last-Modified必須保持一致眼耀,以免負載均衡到不同機器導致比對失敗佩憾;
- 分布式系統(tǒng)盡量關閉掉ETag(每臺機器生成的ETag都會不一樣)