1. 程式人生 > >瀏覽器快取詳解

瀏覽器快取詳解

瀏覽器快取分為兩種型別:

  • 強快取:也稱為本地快取,不向伺服器傳送請求,直接使用客戶端本地快取資料
  • 協商快取:也稱304快取,向伺服器傳送請求,由伺服器判斷請求檔案是否發生改變。如果未發生改變,則返回304狀態碼,通知客戶端直接使用本地快取;如果發生改變,則直接返回請求檔案。

瀏覽器快取機制的過程如下:

強快取(本地快取)

強快取是最徹底的快取,無需向伺服器傳送請求,通常用於css、js、圖片等靜態資源。瀏覽器傳送請求後會先判斷本地是否有快取。如果無快取,則直接向伺服器傳送請求;如果有快取,則判斷快取是否命中強快取,如果命中則直接使用本地快取,如果沒命中則向伺服器傳送請求。判斷是否命中本地快取的方法有兩種: Expires 

和 Cache-Control 

Expires

Expires是http1.0的響應頭,代表的含義是資源本地快取的過期時間,由伺服器設定。伺服器返回給瀏覽器的響應頭中如果包含Expires欄位,瀏覽器傳送請求時拿當前時間和Expires欄位值進行比較,判斷資源快取是否失效。如下圖所示:

date 代表請求資源的時間, expires 代表資源快取的過期時間。2018-9-26 03:57:58之前,請求這個資源就是命中本地快取。超過這個時間再去請求則不命中。很多時候會發現這個時間和本地時間不相同,因為它使用的是伺服器上時間。

Cache-Control

Cache-Control是http1.0中新增的欄位。由於Expires設定的是資源的具體過期時間,如果伺服器時間和客戶端時間不一樣,就會造成快取錯亂,比如認為調節了客戶端的時間,所以設定資源有效期的時長更合理。http1.1添加了Cache-Control的max-age欄位。max-age代表的含義是資源有效期的時長,是一個相對時長,單位為s。Cache-Control: max-age = 300設定資源的過期時間為5分鐘。瀏覽器再次傳送請求時,會把第一次請求的時間和max-age欄位值相加和當前時間比較,以此判斷是否命中本地快取。max-age使用的都是客戶端時間,比Expires更可靠。如果max-age和Expires同時出現,max-age的優先順序更高。所以在上圖中,實際生效的是Cache-Control。Cache-Control提供了更多的欄位來控制快取:

  • no-store,不判斷強快取和協商快取,伺服器直接返回完整資源
  • no-cache,不判斷強快取,每次都需要向瀏覽器傳送請求,進行協商快取判斷
  • public,指示響應可被任何快取區快取
  • private,通常只為單個使用者快取,不允許任何共享快取對其進行快取,通常用於使用者個人資訊

協商快取

協商快取的判斷在伺服器端進行,判斷是否命中的依據就是這次請求和上次請求之間資源是否發生改變。未發生改變命中,發生改變則未命中。判斷檔案是否發生改變的方法有兩個: Last-ModifiedIf-Modified-Since 和 EtagIf-None-Match 。

Last-Modified、If-Modified-Since

Last-Modified是http1.0中的響應頭欄位,代表請求的資源最後一次的改變時間。If-Modified-Since是http1.0的請求頭,If-Modified-Since的值是上次請求伺服器返回的Last-Modified的值。瀏覽器第一次請求資源時,伺服器返回Last-Modified,瀏覽器快取該值。瀏覽器第二次請求資源時,用於快取的Last-Modified賦值給If-Modified-Since,傳送給伺服器。伺服器判斷If-Modified-Since和伺服器本地的Last-Modified是否相等。如果相等,說明資源未發生改變,命中協商快取;如果不相等,說明資源發生改變,未命中協商快取。可以看到該請求返回的是304狀態碼,說明資源的Last-Modified未改變,所以這次請求的Last-Modified和If-Modified-Since是一致的。

Etag、If-None-Match

Last-Modified、If-Modified-Since使用的都是伺服器提供的時間,所以相對來說還是很可靠的。但是由於修改時間的精確級別或者定期生成檔案這種情況,會造成一定的錯誤。所以http1.1新增Etag、If-None-Match欄位,完善協商快取的判斷。Etag是根據資原始檔內容生成的資源唯一識別符號,一旦資源內容發生改變,Etag就會發生改變。基於內容的識別符號比基於修改時間的更可靠。If-None-Match的值是上次請求伺服器返回的Etag的值。Etag、If-None-Match的判斷過程和Last-Modified、If-Modified-Since一致,Etag、If-None-Match的優先順序更高。所以圖中所示應該是Etag、If-None-Match生效