前言
為什么要使用緩存伯诬?
1. 可以加快頁面打開速度
一個優(yōu)秀的緩存策略可以縮短網(wǎng)頁請求資源的距離(例如從本地緩存獲取)巫财,降低延遲姑廉,從而實現(xiàn)頁面打開速度;
2. 減少網(wǎng)絡請求或減少冗余的數(shù)據(jù)傳輸
被緩存的文件在過期時間內(nèi)是可以被重復利用的翁涤,可以減少對該資源的請求(減小服務器壓力)或者只是請求驗證該資源是否改變(未改變則沒有響應體/減少冗余的數(shù)據(jù)傳輸)
瀏覽器緩存分為本地緩存(強緩存),協(xié)商緩存(再驗證)兩個階段萌踱。
注:緩存機制主要在http響應頭中設(shè)定葵礼,響應頭中相關(guān)字段為Expires
、Cache-Control
并鸵、Last-Modified
鸳粉、Etag
。
注:Cache-Control
是通用頭部(既可以是響應頭也可以是請求頭)
本地緩存
本地緩存的實現(xiàn)
HTTP 有兩個響應首部用來控制瀏覽器是否進行本地緩存: Expires
和 Cache-Control
园担。HTTP 允許原始服務器向每個文檔附加一個“過期日期”届谈,說明可以在多長時間內(nèi)將這些內(nèi)容視為新鮮的。
1. Expires
相對于 Cache-Control弯汰,Expires 是一個較老的首部(HTTP/1.0)艰山,其接受一個 Date 值指定文件的過期日期。該值是一個絕對日期咏闪,瀏覽器判斷文件是否過期時曙搬,對比的是用戶機器上的時間而不是服務器上的時間。所以使用 Expires 首部可能會出現(xiàn)的一個問題
就是,用戶本地時間是會影響到原先的緩存意圖的纵装。
2.Cache-Control
為了解決Expires 的問題征讲,HTTP/1.1 的Cache-Control應運而生。Cache-Control 接受一個秒數(shù)作為文檔的生存時間橡娄。這個時間是一個相對時間诗箍,一個倒計時的秒數(shù),不依賴于機器時間挽唉。
啟用本地緩存時滤祖,選用其中一個首部即可,推薦使用較新的 Cache-Control 橱夭。如果同時使用 Expires
和 Cache-Control
首部氨距,那么瀏覽器將以優(yōu)先值更高的 Cache-Control
為準。
如果文件是通過緩存獲得的棘劣,network 上該資源的請求會顯示200 OK (from disk/memory cache)俏让,此時該請求是不會發(fā)送到原始服務器的。
from disk cache
:一般非腳本會存在內(nèi)存當中茬暇,如css首昔,html等from memory cache
:資源在內(nèi)存當中,一般腳本糙俗、字體勒奇、圖片會存在內(nèi)存當
Cache-Control 控制緩存的能力
Cache-Control 有一些可選值,可以用來控制緩存方式巧骚。
-
Cache-Control: no-store
赊颠,標識為 no-store 的響應會禁止緩存對響應進行拷貝。 -
Cache-Contro: no-cache
劈彪,標識為 no-cache 的響應實際上是可以存儲在本地緩存區(qū)中的竣蹦。只是在與原始服務器進行新鮮度再驗證之前,緩存不能將其提供給客戶端使用沧奴。這個首部使用 do-not-serve-from-cache-without-revalidation 這個名字會更恰當一些痘括。 -
Cache-Control: max-age
,表示的是從服務器將文檔傳來之時起滔吠,可以認為此文檔處于新鮮狀態(tài)的秒數(shù)纲菌。 -
Cache-Control:must-revalidate
,可配置緩存疮绷,這個響應首部告訴緩存翰舌,在實現(xiàn)沒有跟原始服務器進行再驗證的情況下,不能使用這個對象的陳舊副本矗愧。服務器通過返回 304 Not Modified 可以讓客戶端使用緩存陳舊(過期)的文檔灶芝,以提高性能郑原。當然,服務器也可以隨意提供新鮮的副本夜涕。如果在緩存進行 must-revalidate 新鮮度檢查時犯犁,原始服務器不可用,緩存就必須返回一條 504 Gateway Timeout 錯誤女器。
本地緩存會有緩存命中和緩存未命中兩種情況
協(xié)商緩存
協(xié)商緩存就是當本地緩存超過緩存期限后酸役,此時用戶再次發(fā)起該資源的請求的話,瀏覽器攜帶緩存標識
向服務器發(fā)起請求驾胆,由服務器根據(jù)緩存標識決定是否繼續(xù)使用該本地緩存的過程涣澡;
根據(jù)服務器上的該資源是否發(fā)生更新,瀏覽器響應分為兩種情況:
- 當服務器的資源
未發(fā)生更新
時(協(xié)商緩存生效
)丧诺,服務器會返回304 Not Modified響應入桂,不會返回文檔的主體,這樣一來驳阎,網(wǎng)絡請求效率就會比普通 GET 請求高一點抗愁。
- 當服務器的資源
發(fā)生更新
時(協(xié)商緩存失效
),服務器會返回200響應呵晚,并在報文體中攜帶新的文件內(nèi)容蜘腌,這種情況下,與普通 GET 請求獲取資源效率無異饵隙。
協(xié)商緩存的實現(xiàn)
協(xié)商緩存可以通過設(shè)置兩種 HTTP Response/Request Header
實現(xiàn):Last-Modified/If-Modified-Since
和 ETag/If-None-Match
撮珠。
Last-Modified/If-Modified-Since
瀏覽器在第一次訪問資源時,服務器返回資源的同時金矛,在
response header
中添加一個屬性名為 Last-Modified的header芯急,其屬性值是這個資源在服務器上的最后修改時間;
瀏覽器下一次請求這個資源驶俊,瀏覽器檢測到有 Last-Modified這個header志于,于是添加If-Modified-Since這個header,值就是Last-Modified中的值废睦;
服務器再次收到這個資源請求,會根據(jù) If-Modified-Since 中的值與服務器中這個資源的最后修改時間對比养泡,如果沒有變化嗜湃,返回304和空的響應體,直接從緩存讀取澜掩,如果If-Modified-Since的時間小于服務器中這個資源的最后修改時間购披,說明文件有更新,于是返回新的資源文件和200
Last-Modified的問題
- 如果本地打開緩存文件肩榕,即使沒有對文件進行修改刚陡,但還是會造成 Last-Modified 被修改惩妇,服務端不能命中緩存導致發(fā)送相同的資源
- 因為 Last-Modified 只能以秒計時,如果在不可感知的時間內(nèi)修改完成文件筐乳,那么服務端會認為資源還是命中了歌殃,不會返回正確的資源
既然根據(jù)文件修改時間來決定是否緩存尚有不足,能否可以直接根據(jù)文件內(nèi)容是否修改來決定緩存策略蝙云?所以在 HTTP / 1.1 出現(xiàn)了 ETag 和If-None-Match
ETag/If-None-Match
Etag是服務器響應資源請求時氓皱,返回當前資源文件的一個唯一標識(由服務器生成),只要該資源有變化勃刨,Etag就會重新生成波材。
瀏覽器在第一次訪問資源時,服務器返回資源的同時身隐,在
response header
中添加一個屬性名為ETag的header廷区,其屬性值是這個資源在服務器上的最后一次修改時生成的唯一標識;
瀏覽器在下一次加載資源向服務器發(fā)送請求時贾铝,會將上一次返回的Etag值放到
request header
里的If-None-Match
里隙轻。
服務器只需要比較客戶端傳來的
If-None-Match
跟自己服務器上該資源的ETag是否一致,就能很好地判斷資源相對客戶端而言是否被修改過了忌傻。如果服務器發(fā)現(xiàn)ETag匹配不上大脉,那么直接以常規(guī)GET 200回包形式將新的資源(當然也包括了新的ETag)發(fā)給客戶端;如果ETag是一致的水孩,則直接返回304知會客戶端直接使用本地緩存即可镰矿。
兩種協(xié)商緩存之間的對比:
- 首先在精確度上,Etag要優(yōu)于Last-Modified俘种。
- 第二在性能上秤标,Etag要遜于Last-Modified,畢竟Last-Modified只需要記錄時間宙刘,而Etag需要服務器通過算法來計算出一個hash值苍姜。
- 第三在優(yōu)先級上,服務器校驗優(yōu)先考慮Etag
緩存流程
強制緩存優(yōu)先于協(xié)商緩存進行悬包,若強制緩存(Expires和Cache-Control)生效則直接使用緩存衙猪,若不生效則進行協(xié)商緩存(Last-Modified / If-Modified-Since和Etag / If-None-Match),協(xié)商緩存由服務器決定是否使用緩存布近,若協(xié)商緩存失效垫释,那么代表該請求的緩存失效,返回200撑瞧,重新返回資源和緩存標識棵譬,再存入瀏覽器緩存中;生效則返回304预伺,繼續(xù)使用緩存订咸。
- 在瀏覽器第一次發(fā)起請求時曼尊,本地無緩存,向web服務器發(fā)送請求脏嚷,服務器起端響應請求骆撇,瀏覽器端緩存。過程如下:
- 瀏覽器后續(xù)再次進行請求時:
疑問
Q:如果什么緩存策略都沒設(shè)置然眼,那么瀏覽器會怎么處理艾船?
A:對于這種情況,瀏覽器會采用一個啟發(fā)式的算法高每,通常會取響應頭中的 Date 減去 Last-Modified 值的 10% 作為緩存時間屿岂。
用戶行為對瀏覽器緩存的影響
參考:
http://www.yangzicong.com/article/12
http://www.reibang.com/p/54cc04190252
https://www.cnblogs.com/slly/p/6732749.html
https://juejin.im/post/5ccfccaff265da03ab233bf5