對瀏覽器緩存的知識小結

瀏覽器緩存分為強緩存和協商緩存:

1)瀏覽器在加載資源時,先根據這個資源的一些http header判斷它是否命中強緩存,強緩存如果命中,瀏覽器直接從自己的緩存中讀取資源,不會發請求到服務器。比如某個css文件,如果瀏覽器在加載它所在的網頁時,這個css文件的緩存配置命中了強緩存,瀏覽器就直接從緩存中加載這個css,連請求都不會發送到網頁所在服務器;

2)當強緩存沒有命中的時候,瀏覽器一定會發送一個請求到服務器,通過服務器端依據資源的另外一些http header驗證這個資源是否命中協商緩存,如果協商緩存命中,服務器會將這個請求返回,但是不會返回這個資源的數據,而是告訴客戶端可以直接從緩存中加載這個資源,于是瀏覽器就又會從自己的緩存中去加載這個資源;

3)強緩存與協商緩存的共同點是:如果命中,都是從客戶端緩存中加載資源,而不是從服務器加載資源數據;區別是:強緩存不發請求到服務器,協商緩存會發請求到服務器。

4)當協商緩存也沒有命中的時候,瀏覽器直接從服務器加載資源數據。

強緩存原理

強緩存是利用Expires或者Cache-Control這兩個http response header實現的,它們都用來表示資源在客戶端緩存的有效期。
Expires是http1.0提出的一個表示資源過期時間的header,它描述的是一個絕對時間,由服務器返回,用GMT格式的字符串表示,如:Expires:Thu, 31 Dec 2037 23:55:55 GMT,它的緩存原理是:
1)瀏覽器第一次跟服務器請求一個資源,服務器在返回這個資源的同時,在respone的header加上Expires的header,如:

捕獲.PNG

2)瀏覽器在接收到這個資源后,會把這個資源連同所有response header一起緩存下來(所以緩存命中的請求返回的header并不是來自服務器,而是來自之前緩存的header);
3)瀏覽器再請求這個資源時,先從緩存中尋找,找到這個資源后,拿出它的Expires跟當前的請求時間比較,如果請求時間在Expires指定的時間之前,就能命中緩存,否則就不行。
4)如果緩存沒有命中,瀏覽器直接從服務器加載資源時,Expires Header在重新加載的時候會被更新。
Expires是較老的強緩存管理header,由于它是服務器返回的一個絕對時間,在服務器時間與客戶端時間相差較大時,緩存管理容易出現問題,比如隨意修改下客戶端時間,就能影響緩存命中的結果。所以在http1.1的時候,提出了一個新的header,就是Cache-Control,這是一個相對時間,在配置緩存的時候,以秒為單位,用數值表示,如:Cache-Control:max-age=315360000,它的緩存原理是:
1)瀏覽器第一次跟服務器請求一個資源,服務器在返回這個資源的同時,在respone的header加上Cache-Control的header,如:

捕獲1.PNG

2)瀏覽器在接收到這個資源后,會把這個資源連同所有response header一起緩存下來;
3)瀏覽器再請求這個資源時,先從緩存中尋找,找到這個資源后,根據它第一次的請求時間和Cache-Control設定的有效期,計算出一個資源過期時間,再拿這個過期時間跟當前的請求時間比較,如果請求時間在過期時間之前,就能命中緩存,否則就不行。
4)如果緩存沒有命中,瀏覽器直接從服務器加載資源時,Cache-Control Header在重新加載的時候會被更新。
Cache-Control描述的是一個相對時間,在進行緩存命中的時候,都是利用客戶端時間進行判斷,所以相比較Expires,Cache-Control的緩存管理更有效,安全一些。
當response header中,Expires和Cache-Control同時存在時,Cache-Control優先級高于Expires

協商緩存

當瀏覽器對某個資源的請求沒有命中強緩存,就會發一個請求到服務器,驗證協商緩存是否命中,如果協商緩存命中,請求響應返回的http狀態為304并且會顯示一個Not Modified的字符串,比如你打開京東的首頁,按f12打開開發者工具,再按f5刷新頁面,查看network,可以看到有不少請求就是命中了協商緩存的:


查看單個請求的Response Header,也能看到304的狀態碼和Not Modified的字符串,只要看到這個就可說明這個資源是命中了協商緩存,然后從客戶端緩存中加載的,而不是服務器最新的資源:
image

協商緩存是利用的是【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】這兩對Header來管理的。
【Last-Modified,If-Modified-Since】的控制緩存的原理是:
1)瀏覽器第一次跟服務器請求一個資源,服務器在返回這個資源的同時,在respone的header加上Last-Modified的header,這個header表示這個資源在服務器上的最后修改時間:
image

2)瀏覽器再次跟服務器請求這個資源時,在request的header上加上If-Modified-Since的header,這個header的值就是上一次請求時返回的Last-Modified的值:
無標題

3)服務器再次收到資源請求時,根據瀏覽器傳過來If-Modified-Since和資源在服務器上的最后修改時間判斷資源是否有變化,如果沒有變化則返回304 Not Modified,但是不會返回資源內容;如果有變化,就正常返回資源內容。當服務器返回304 Not Modified的響應時,response header中不會再添加Last-Modified的header,因為既然資源沒有變化,那么Last-Modified也就不會改變,這是服務器返回304時的response header:
image

4)瀏覽器收到304的響應后,就會從緩存中加載資源。
5)如果協商緩存沒有命中,瀏覽器直接從服務器加載資源時,Last-Modified Header在重新加載的時候會被更新,下次請求時,If-Modified-Since會啟用上次返回的Last-Modified值。
【Last-Modified,If-Modified-Since】都是根據服務器時間返回的header,一般來說,在沒有調整服務器時間和篡改客戶端緩存的情況下,這兩個header配合起來管理協商緩存是非常可靠的,但是有時候也會服務器上資源其實有變化,但是最后修改時間卻沒有變化的情況,而這種問題又很不容易被定位出來,而當這種情況出現的時候,就會影響協商緩存的可靠性。所以就有了另外一對header來管理協商緩存,這對header就是【ETag、If-None-Match】。它們的緩存管理的方式是:
1)瀏覽器第一次跟服務器請求一個資源,服務器在返回這個資源的同時,在respone的header加上ETag的header,這個header是服務器根據當前請求的資源生成的一個唯一標識,這個唯一標識是一個字符串,只要資源有變化這個串就不同,跟最后修改時間沒有關系,所以能很好的補充Last-Modified的問題:
image

2)瀏覽器再次跟服務器請求這個資源時,在request的header上加上If-None-Match的header,這個header的值就是上一次請求時返回的ETag的值:
image

3)服務器再次收到資源請求時,根據瀏覽器傳過來If-None-Match和然后再根據資源生成一個新的ETag,如果這兩個值相同就說明資源沒有變化,否則就是有變化;如果沒有變化則返回304 Not Modified,但是不會返回資源內容;如果有變化,就正常返回資源內容。與Last-Modified不一樣的是,當服務器返回304 Not Modified的響應時,由于ETag重新生成過,response header中還會把這個ETag返回,即使這個ETag跟之前的沒有變化:
image

4)瀏覽器收到304的響應后,就會從緩存中加載資源。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 瀏覽器緩存,也就是客戶端緩存,既是網頁性能優化里面靜態資源相關優化的一大利器,也是無數web開發人員在工作過程不可...
    單純的土豆閱讀 416評論 0 1
  • 轉載:瀏覽器緩存知識小結及應用 閱讀目錄 1. 瀏覽器緩存基本認識 2. 強緩存的原理 3. 強緩存的管理 4. ...
    meng_philip123閱讀 1,098評論 4 18
  • 瀏覽器緩存,也就是客戶端緩存,既是網頁性能優化里面靜態資源相關優化的一大利器,也是無數web開發人員在工作過程不可...
    Www劉閱讀 574評論 0 1
  • 瀏覽器緩存概述 瀏覽器緩存分為強緩存和協商緩存。當客戶端請求某個資源時,獲取緩存的流程如下: 先根據這個資源的一些...
    單純的土豆閱讀 295評論 0 0
  • 最近一直在做一個選擇,是做一個正常的職人也是一個名撲克玩家。很顯然,出現了這個選擇的原因是,做一個撲克玩家對我的誘...
    joeyshaw閱讀 809評論 0 1