今天被一個后端同學(xué)給問住了,為什么200狀態(tài)碼后面有一個from memary cache?一時竟然答不上來。為了徹底搞懂瀏覽器緩存,決定深入研究下。本次以chrome瀏覽器為例:
瀏覽器緩存分為兩類:
1.強(qiáng)制緩存
2.協(xié)商緩存:也有稱作“對比緩存”
首先強(qiáng)制緩存和協(xié)商緩存,都是指HTTP的緩存--即發(fā)生在應(yīng)用層
強(qiáng)制緩存:
用戶發(fā)送的請求,直接從客戶端緩存中獲取,不發(fā)送請求到服務(wù)器,不與服務(wù)器發(fā)生交互行為
協(xié)商緩存:
用戶發(fā)送的請求,發(fā)送到服務(wù)器后,由服務(wù)器判定是否從緩存中獲取資源
共同點(diǎn):強(qiáng)制緩存和協(xié)商緩存,緩存都存在客戶端。
不同點(diǎn):協(xié)商緩存需要與服務(wù)器交互。
具體看下這兩種緩存怎么實(shí)現(xiàn):
什么是客戶端緩存?
所謂“客戶端緩存”就是指客戶端將網(wǎng)絡(luò)資源保存在用戶設(shè)備中,可能保存在你的硬盤中,內(nèi)存中等等等,下次瀏覽同一個資源時,不再從網(wǎng)絡(luò)下載,實(shí)則是客戶端從你的設(shè)備中獲取的,不同瀏覽器緩存文件的地址也不盡相同。
以chrome瀏覽器為例:查看緩存
1.在chrome中輸入chrome://version能看到瀏覽器的大部分信息如圖:

復(fù)制出個人資料路徑file:///C:/Users/Administrator/AppData/Local/Google/Chrome/,去掉后面的User,因?yàn)閹蟄ser可能打不開,因?yàn)槟愕臄?shù)據(jù)在user data下面如圖:

點(diǎn)擊User Data

點(diǎn)擊Default

cache緩存文件所在位置。當(dāng)前緩存文件的URL列表,點(diǎn)擊url可以看到對應(yīng)的緩存文件內(nèi)容,包括類型 編碼 過期時間等概要信息,以及文件內(nèi)容等具體信息,以二進(jìn)制方式顯示。
接下來我是使用chromecacheview查看緩存。
工具已經(jīng)到位,接下驗(yàn)證緩存
驗(yàn)證緩存:
打開百度,ctrl+shift+I或者F12或者鼠標(biāo)右鍵-檢查,打開開發(fā)者模式,不勾選disable-cache選項(xiàng)。

刷新網(wǎng)頁可以看到from memory cache(紅框內(nèi))表示從緩存中獲取的文件,打開chromeViewCache工具ctrl+f搜索bd_logo1.png

紅色框內(nèi)的就是本地緩存的bd_logo1.png的信息。也就是服務(wù)端返回給我們的response header信息。
前面提到了強(qiáng)制緩存和協(xié)商緩存:
圖中expires和Cache-Control兩個字段控制強(qiáng)制緩存。
介紹一下這個兩個字段:
expires緩存原理:Http1.0 中的標(biāo)準(zhǔn),表明過期時間,注意此處的時間都是指的是服務(wù)器的時間。
1. 瀏覽器第一次請求資源,瀏覽求返回資源的同時會在response header里面添加Expires。
2. 瀏覽器請求到資源時,會一同把資源和Expires緩存起來。
3. 瀏覽器再次請求同一個資源時,會先從瀏覽器緩存中獲取,然后用客戶端時間和緩存2步驟里緩存的expires作比較。小于緩存的expires表示使用緩存,否則從服務(wù)器獲取。
4. 緩存過期也就是客戶端時間大于expires,會再次從服務(wù)器獲取資源,并且更新expires。
5. expires是http1.0的產(chǎn)物,已經(jīng)過時。由于客戶端時間可以隨意修改,緩存容易出現(xiàn)問題。所以在http1.1之中使用了相對時間,cache-control: max-age=1000(注意單位是秒)
Cache-Control的緩存原理:
cache-control屬性值:
max-age: 設(shè)置緩存的最大的有效時間,單位為秒(s)。max-age會覆蓋掉Expires
?s-maxage: 只用于共享緩存,比如CDN緩存(s -> share)。與max-age 的區(qū)別是:max-age用于普通緩存,而s-maxage用于代理緩存。如果存在s-maxage,則會覆蓋max-age 和 Expires.
public:響應(yīng)會被緩存,并且在多用戶間共享。默認(rèn)是public。
private: 響應(yīng)只作為私有的緩存,不能在用戶間共享。如果要求HTTP認(rèn)證,響應(yīng)會自動設(shè)置為private。
no-cache: 指定不緩存響應(yīng),表明資源不進(jìn)行緩存。但是設(shè)置了no-cache之后并不代表瀏覽器不緩存,而是在緩存前要向服務(wù)器確認(rèn)資源是否被更改。因此有的時候只設(shè)置no-cache防止緩存還是不夠保險(xiǎn),還可以加上private指令,將過期時間設(shè)為過去的時間。
no-store: 絕對禁止緩存。
must-revalidate: 如果頁面過期,則去服務(wù)器進(jìn)行獲取。
當(dāng)瀏覽器命中強(qiáng)制緩存時:出現(xiàn)兩種狀態(tài)200 from disk cache和200 from memory cache.


from memory cache:字面理解是從內(nèi)存中,其實(shí)也是字面的含義,這個資源是直接從內(nèi)存中拿到的,不會請求服務(wù)器一般已經(jīng)加載過該資源且緩存在了內(nèi)存當(dāng)中,當(dāng)關(guān)閉該頁面時,此資源就被內(nèi)存釋放掉了,再次重新打開相同頁面時不會出現(xiàn)from memory cache的情況.
from disk cache:同上類似,此資源是從磁盤當(dāng)中取出的,也是在已經(jīng)在之前的某個時間加載過該資源,不會請求服務(wù)器但是此資源不會隨著該頁面的關(guān)閉而釋放掉,因?yàn)槭谴嬖谟脖P當(dāng)中的,下次打開仍會from disk cache.
內(nèi)存緩存(from memory cache)和硬盤緩存(from disk cache),如下:
內(nèi)存緩存(from memory cache):內(nèi)存緩存具有兩個特點(diǎn),分別是快速讀取和時效性:
快速讀取:內(nèi)存緩存會將編譯解析后的文件,直接存入該進(jìn)程的內(nèi)存中,占據(jù)該進(jìn)程一定的內(nèi)存資源,以方便下次運(yùn)行使用時的快速讀取。
時效性:一旦該進(jìn)程關(guān)閉,則該進(jìn)程的內(nèi)存則會清空。
硬盤緩存(from disk cache):硬盤緩存則是直接將緩存寫入硬盤文件中,讀取緩存需要對該緩存存放的硬盤文件進(jìn)行I/O操作,然后重新解析該緩存內(nèi)容,讀取復(fù)雜,速度比內(nèi)存緩存慢。
在瀏覽器中,瀏覽器會在js和圖片等文件解析執(zhí)行后直接存入內(nèi)存緩存中,那么當(dāng)刷新頁面時只需直接從內(nèi)存緩存中讀取(from memory cache);而css文件則會存入硬盤文件中,所以每次渲染頁面都需要從硬盤讀取緩存(from disk cache)。
協(xié)商緩存
顧名思義就是跟服務(wù)器協(xié)商是否使用緩存。
比較Last-modified 和 Etag 字段
Last-modified: 表明請求的資源上次的修改時間,服務(wù)器返回的時間,在response header里。
If-Modified-Since:客戶端會保留資源上次的修改時間,也就是Last-modified的時間。
Etag:資源的內(nèi)容標(biāo)識。(不唯一,通常為文件的md5或者一段hash值,只要保證寫入和驗(yàn)證時的方法一致即可)。
If-None-Match: 客戶端保留的資源內(nèi)容標(biāo)識。
瀏覽器將在第二次請求的header中加入If-Modified-Since(對應(yīng)于Last-modified), 和If-None-Match(對應(yīng)于Etag)。
通常情況下,如果同時發(fā)送 If-None-Match 、If-Modified-Since字段,服務(wù)器只要比較etag 的內(nèi)容即可,當(dāng)然具體處理方式,看服務(wù)器的約定規(guī)則。
Last-modified和If-Modified-Since:看下返回結(jié)果,設(shè)置Last-modified固定時間123456

看下第一請求:只有response有l(wèi)ast-modify,請求頭里并沒有If-Modified-Since。因?yàn)槭堑谝徽埱?,瀏覽器并未緩存。

再次請求,Last-modified和If-Modified-Since一致,返回status: 304,告訴瀏覽器使用瀏覽器緩存。

Etag和If-None-Match:同上直接上Etag的代碼:
第一次請求:response: Etag-123456。request:header并沒If-None-Match,狀態(tài):200


第二次請求:
