瀏覽器緩存總結

最近一直被瀏覽器的緩存行爲所困擾,因此換了一番功夫做一次總結,話不多說直接進入正題。

瀏覽器的緩存策略包括兩種:強緩存協商緩存

強緩存

強緩存即直接從本地讀取緩存副本,不需要向服務器發起請求,這種方式是最快的。

HTTP 1.0   使用 Expires指定資源的失效時間,如expires:Fri, 14 Apr 2018 00:00:00 GMT。只要發送請求時間是在Expires之前,那麼本地緩存始終有效,直接從本地緩存中讀取數據,不去請求服務器。所以這種方式有一個明顯的缺點,由於失效的時間是一個絕對時間,所以當服務器與客戶端時間偏差較大時,就會導致緩存混亂。

HTTP 1.1 使用Cache-Control(優先級高於Expires),主要的取值有以下幾種:

  • max-age:它是一個相對時間,例如Cache-Control:max-age=3600,代表着資源的有效期是3600秒。

  • no-cache:不使用本地緩存。需要使用緩存協商,先與服務器確認返回的響應是否被更改,如果之前的響應中存在ETag,那麼請求的時候會與服務端驗證,如果資源未被更改,則可以避免重新下載。

  • no-store:直接禁止遊覽器緩存數據,每次用戶請求該資源,都會向服務器發送一個請求,每次都會下載完整的資源。

  • public:可以被所有的用戶緩存,包括終端用戶和CDN等中間代理服務器。

  • private:只能被終端用戶的瀏覽器緩存,不允許CDN等中繼緩存服務器對其緩存。

協商緩存

協商緩存就是由服務器來確定緩存資源是否可用,所以客戶端與服務器端要通過某種標識來進行通信,從而讓服務器判斷請求資源是否可以緩存訪問。

HTTP 1.0 使用Last-Modify(服務端)/ If-Modify-Since(客戶端)

瀏覽器第一次請求一個資源的時候,服務器返回的header中會加上Last-Modify,Last-modify是一個時間標識該資源的最後修改時間,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。

當瀏覽器再次請求該資源時,request的請求頭中會包含If-Modify-Since,該值爲緩存之前返回的Last-Modify。服務器收到If-Modify-Since後,根據資源的最後修改時間判斷是否命中緩存。

如果命中緩存,則返回304,並且不會返回資源內容,並且不會返回Last-Modify。這套緩存策略會存在以下幾個問題:

  • 一些文件也許會週期性的更改,但是他的內容並不改變(僅僅改變的修改時間),這個時候我們並不希望客戶端認爲這個文件被修改了,而重新GET;

  • 某些文件修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒);

  • 某些服務器不能精確的得到文件的最後修改時間。

HTTP 1.1 使用Etag(服務端)/ If-None-Match(客戶端)

Etag/If-None-Match返回的是一個校驗碼。ETag可以保證每一個資源是唯一的,資源變化都會導致ETag變化。服務器根據瀏覽器上送的If-None-Match值來判斷是否命中緩存。

與Last-Modified不一樣的是,當服務器返回304 Not Modified的響應時,由於ETag重新生成過,response header中還會把這個ETag返回,即使這個ETag跟之前的沒有變化。

以上內容可以總結爲下圖(來自於網絡)

 

下面是我對強緩存Cache-Control的幾種值的實驗結果:

no-store

  • F5、地址欄回車時,html以及html內部的靜態資源都會向服務器請求資源,狀態碼200
  • 前進回退時,html向服務器請求資源,但是html內部的其他靜態資源會from cache

no-cache

  • F5、地址欄回車時,所有資源都會向服務器請求資源,狀態碼304,服務器只返回頭部信息;如果修改了文件,服務器會重新生成這個資源的ETag,而瀏覽器請求時request headers裏的還是上次服務器給的ETag,服務器會直接返回頭部信息和消息主體;
  • 前進回退時,所有資源都是from cache。即使資源修改了,也是from cache

max-age=10 10秒鐘過期

  •  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章