歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~
瀏覽器快取,是瀏覽器端儲存資料,用於快速讀取或避免重複資源請求的優化機制,有效的快取使用可以避免重複的網路請求和加快頁面速度,從而提高使用者體驗。
一 強快取
1.1 區分Expires和Cache-Control
以一個介面返回的響應頭為例:
這裡我畫了張思維導圖,對Expires和Cache-Control做比較:
具體介紹Expires和Cache-Control:
Expires:
(1)Expires是HTTP1.0的東西,現在預設瀏覽器均預設使用HTTP 1.1,所以它的作用基本忽略;
(2)Expires規定了快取失效時間(Date為當前時間),是絕對時間。由於Expires返回的是一個絕對時間,在伺服器時間與客戶端時間相差較大的時候,快取命中不準確;
Cache-Control:
(1)Cache-Control是HTTP1.1的
(2)Cache-Control的max-age規定了快取有效時間(2552s),是相對時間;
(3)若響應頭Expires和Cache-Control同時存在,Cache-Control優先順序高於Expires
Cache-Control的常用指令:
no-cache:不使用本地快取,需要使用協商快取,也就是先與伺服器確認快取是否可用。
no-store:禁用快取。用於防止重要的資訊被無意的釋出。在請求訊息中傳送將使得請求和響應訊息都不使用快取。
public:其他使用者也可使用快取,適用於公共快取伺服器的情況。
private:只有特定使用者才能使用快取,適用於公共快取伺服器的情況。
max-age:客戶機可以接收生存期不大於指定時間(以秒為單位)的響應。
min-fresh客戶機可以接收響應時間小於當前時間加上指定時間的響應。
max-stale指示客戶機可以接收超出超時期間的響應訊息。如果指定max-stale訊息的值,那麼客戶機可以接收超出超時期指定值之內的響應訊息。
注意:no-cache指令並不是不快取,no-cache的意思是可以快取,但每次用應該去向伺服器驗證快取是否可用。no-store才是不快取內容。
1.2 強快取的過程
**強快取:**瀏覽器直接從本地快取中獲取資料,不與伺服器進行互動。
· 瀏覽器第一次跟伺服器請求一個資源,伺服器在返回這個資源的同時,在response的header會加上Expires/Cache-Control的header;
· 瀏覽器再請求這個資源時,先從快取中尋找,找到這個資源後,比較Expires或Cache-Control的max-age欄位值做比較, 如果在有效期內,則讀取快取內容;若快取已過期,則重新向伺服器傳送請求;
· header在重新載入的時候會被更新
這裡我畫了兩張圖,瀏覽器第一次請求:
瀏覽器第一次請求瀏覽器再次請求:
強快取對於強快取,chrome瀏覽器的狀態碼:
200 OK(from disk cache)或是200 OK (from memory cache)
例如:請求某個圖片後,當瀏覽器再次訪問這個圖片時,發現有這個圖片的快取,且快取沒過期,所以就使用快取。
當瀏覽器發現快取過期後,快取並不一定不能使用了。比如檔案雖然過了有效期,但內容並沒有發生改變,還是可以用快取資料。所以,這個時候需要與伺服器協商,讓伺服器判斷本地快取是否還能使用。那麼又怎麼判斷服務端檔案有沒有更新呢?主要有兩種方式:
Last-Modified,If-Modified-since。
二 協商快取
2.1 區分Last-Modified和If-Modified-Since
以一個返回的介面為例:
Last-Modified的格式:
Last-Modified: Mon, 17 Sep 2018 12:06:18 GMT
If-Modified-Since的格式:
If-Modified-Since: Mon, 17 Sep 2018 12:06:18 GMT
2.2 Etag是什麼
web伺服器響應請求時,告訴瀏覽器當前資源在伺服器的唯一標識(生成規則由伺服器決定)。Apache中,ETag的值預設是對檔案的索引節(INode),大小(Size)和最後修改時間(MTime)進行Hash後得到的。
2.3 協商快取的過程
瀏覽器第一次請求:
瀏覽器第一次快取瀏覽器再一次請求:
協商快取Last-Modified、If-Modified-Since:
· 瀏覽器第一次向伺服器請求一個資源,伺服器在返回這個資源的同時,在respone的header加上Last-Modified欄位,表示該資源在伺服器上的最後修改時間;
· 瀏覽器再次向伺服器請求這個資源時,在request的header上加上If-Modified-Since欄位,這個值就是上一次請求時返回的Last-Modified的值;
·伺服器收到資源請求時,比較If-Modified-Since欄位值和被請求資源的最後修改時間,若資源最後修改時間較舊,則說明檔案沒有修改,返回304 Not Modified, 瀏覽器從快取中載入資源;若不相同,說明檔案被更新,瀏覽器直接從伺服器載入資源, 返回200;
·重新載入資源時更新Last-Modified Header
Etag、If-None-Match
· 瀏覽器第一次向伺服器請求一個資源,伺服器在返回這個資源的同時,在respone的header加上ETag欄位;
·瀏覽器再次跟伺服器請求這個資源時,在request的header上加上If-None-Match,這個值就是上一次請求時返回的ETag的值;
·伺服器再次收到資源請求時,再根據資源生成一個新的ETag,與瀏覽器傳過來If-None-Match比較,如果這兩個值相同,則說明資源沒有變化,返回304 Not Modified, 瀏覽器從快取中載入資源,否則返回200 資源內容。與Last-Modified不一樣的是,當伺服器返回304 Not Modified的響應時,由於ETag重新生成過,response header中還會把這個ETag返回,即使這個ETag跟之前的沒有變化
2.4 為什麼有了Last-Modified,還要用Etag呢?
HTTP1.1中ETag的出現主要是為了解決幾個Last-Modified比較難解決的問題:
·一些檔案也許會週期性的更改,但是他的內容並不改變(僅僅改變的修改時間),這個時候我們並不希望客戶端認為這個檔案被修改了,而重新GET;
·某些檔案修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒);
·某些伺服器不能精確的得到檔案的最後修改時間。
對於上述情景,利用ETag能夠更加準確的控制快取,因為ETag是伺服器自動生成的資源在伺服器端的唯一識別符號,資源每次變動,都會生成新的ETag值。Last-Modified與ETag是可以一起使用的,但伺服器會優先驗證ETag。
2.5 比較強快取和協商快取
基於上文對強快取和協商快取過程的解釋,這裡我把強快取和協商快取繪製在一張圖裡,方便比較,具體過程可以參照上文:
http快取三 小結
本文主要通過圖解介紹了http的快取,具體包括強快取和協商快取。如有問題,歡迎指正。
此文已由作者授權騰訊雲+社群釋出,更多原文請點選
搜尋關注公眾號「雲加社群」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!
海量技術實踐經驗,盡在雲加社群!