[人云亦云]http 的快取機制

Quinggor發表於2019-04-17

強快取與協商快取

1)瀏覽器在載入資源時,先根據這個資源的一些http header判斷它是否命中強快取,強快取如果命中,瀏覽器直接從自己的快取中讀取資源,不會發請求到伺服器。 在network中,能抓到請求的情況,強制快取的狀態碼是 status:灰色的200. size : from memory cache

[人云亦云]http 的快取機制

狀態碼灰色兩百,不一定是讀取快取:

[人云亦云]http 的快取機制

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

強快取

[人云亦云]http 的快取機制

expires

  1. 瀏覽器第一次跟伺服器請求一個資源,伺服器在返回這個資源的同時,在respone的header加上Expires的header

  2. 瀏覽器在接收到這個資源後,會把這個資源連同所有response header一起快取下來(所以快取命中的請求返回的header並不是來自伺服器,而是來自之前快取的header);

  3. 瀏覽器再請求這個資源時,先從快取中尋找,找到這個資源後,拿出它的Expires跟當前的請求時間比較,如果請求時間在Expires指定的時間之前,就能命中快取,否則就不行。

  4. 如果快取沒有命中,瀏覽器直接從伺服器載入資源時,Expires Header在重新載入的時候會被更新。

[人云亦云]http 的快取機制

cache-Control

Expires是較老的強快取管理header,由於它是伺服器返回的一個絕對時間,在伺服器時間與客戶端時間相差較大時,快取管理容易出現問題,比如隨意修改下客戶端時間,就能影響快取命中的結果。所以在http1.1的時候,提出了一個新的header,就是Cache-Control,這是一個相對時間,在配置快取的時候,以秒為單位,用數值表示,如:Cache-Control:max-age=315360000,它的快取原理是:

  1. 瀏覽器第一次跟伺服器請求一個資源,伺服器在返回這個資源的同時,在respone的header加上Cache-Control的header
  2. 瀏覽器在接收到這個資源後,會把這個資源連同所有response header一起快取下來;
  3. 瀏覽器再請求這個資源時,先從快取中尋找,找到這個資源後,根據它第一次的請求時間和Cache-Control設定的有效期,計算出一個資源過期時間,再拿這個過期時間跟當前的請求時間比較,如果請求時間在過期時間之前,就能命中快取,否則就不行。
  4. 如果快取沒有命中,瀏覽器直接從伺服器載入資源時,Cache-Control Header在重新載入的時候會被更新。

[人云亦云]http 的快取機制

協商快取

當瀏覽器對某個資源的請求沒有命中強快取,就會發一個請求到伺服器,驗證協商快取是否命中,如果協商快取命中,請求響應返回的http狀態為304並且會顯示一個Not Modified的字串

首次訪問的響應頭

[人云亦云]http 的快取機制

第二次訪問的請求頭

[人云亦云]http 的快取機制

第二次請求響應頭

[人云亦云]http 的快取機制

Last-Modified,If-Modified-Since

  1. 瀏覽器第一次跟伺服器請求一個資源,伺服器在返回這個資源的同時,在respone的header加上Last-Modified的header,這個header表示這個資源在伺服器上的最後修改時間
  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;
  4. 瀏覽器收到304的響應後,就會從快取中載入資源。
  5. 如果協商快取沒有命中,瀏覽器直接從伺服器載入資源時,Last-Modified Header在重新載入的時候會被更新,下次請求時,If-Modified-Since會啟用上次返回的Last-Modified值。

[人云亦云]http 的快取機制

ETag、If-None-Match

【Last-Modified,If-Modified-Since】都是根據伺服器時間返回的header,一般來說,在沒有調整伺服器時間和篡改客戶端快取的情況下,這兩個header配合起來管理協商快取是非常可靠的,但是有時候也會伺服器上資源其實有變化,但是最後修改時間卻沒有變化的情況,而這種問題又很不容易被定位出來,而當這種情況出現的時候,就會影響協商快取的可靠性。所以就有了另外一對header來管理協商快取,這對header就是【ETag、If-None-Match】。它們的快取管理的方式是:

  1. 瀏覽器第一次跟伺服器請求一個資源,伺服器在返回這個資源的同時,在respone的header加上ETag的header,這個header是伺服器根據當前請求的資源生成的一個唯一標識,這個唯一標識是一個字串,只要資源有變化這個串就不同,跟最後修改時間沒有關係,所以能很好的補充Last-Modified的問題;
  2. 瀏覽器再次跟伺服器請求這個資源時,在request的header上加上If-None-Match的header,這個header的值就是上一次請求時返回的ETag的值;
  3. 伺服器再次收到資源請求時,根據瀏覽器傳過來If-None-Match和然後再根據資源生成一個新的ETag,如果這兩個值相同就說明資源沒有變化,否則就是有變化;如果沒有變化則返回304 Not Modified,但是不會返回資源內容;如果有變化,就正常返回資源內容。與Last-Modified不一樣的是,當伺服器返回304 Not Modified的響應時,由於ETag重新生成過,response header中還會把這個ETag返回,即使這個ETag跟之前的沒有變化
  4. 瀏覽器收到304的響應後,就會從快取中載入資源。

[人云亦云]http 的快取機制

以下行為可能改變快取的預設處理方式

當ctrl+f5強制重新整理網頁時,直接從伺服器載入,跳過強快取和協商快取;

當f5重新整理網頁時,跳過強快取,但是會檢查協商快取;

相關文章