一、什么是web緩存
? ? 緩存是一種保存資源副本并在下次請求時(shí)直接使用該副本的技術(shù)。當(dāng) web 緩存發(fā)現(xiàn)請求的資源已經(jīng)被存儲(chǔ),它會(huì)攔截請求,返回該資源的拷貝,而不會(huì)去源服務(wù)器重新下載。
????Web 緩存能夠減少延遲與網(wǎng)絡(luò)阻塞,進(jìn)而減少顯示某個(gè)資源所用的時(shí)間。借助 HTTP 緩存,Web 站點(diǎn)變得更具有響應(yīng)性。接下來的內(nèi)容中我們將通過web緩存位置、緩存策略以及實(shí)際場景應(yīng)用緩存策略來探討瀏覽器緩存機(jī)制。
二、緩存位置

上圖是第二次打開某個(gè)網(wǎng)頁的Network資源請求圖,可以看到一些資源是直接從瀏覽器緩存讀取了數(shù)據(jù),具體表現(xiàn)在: status欄為灰色的200;Size欄顯示灰色的memory cache (內(nèi)存緩存)和 disk cache(硬盤緩存)。
那么內(nèi)存緩存和硬盤緩存有什么區(qū)別呢?
內(nèi)存緩存(from memory cache):特點(diǎn)是容量小、快速讀取、時(shí)效性。
內(nèi)存緩存是將編譯解析后的文件,直接存入該進(jìn)程的內(nèi)存中,占據(jù)該進(jìn)程一定的內(nèi)存資源,容量小,但可以保證下次使用緩存資源時(shí)的快速讀取,然鵝一旦該進(jìn)程關(guān)閉,該進(jìn)程的內(nèi)存則會(huì)清空。
硬盤緩存(from disk cache):特點(diǎn)是容量大、讀取緩慢、持續(xù)性長。
硬盤緩存則直接將資源寫入硬盤文件中,讀取緩存需要對(duì)該緩存存放的硬盤文件進(jìn)行I/O操作,然后重新解析該緩存內(nèi)容,讀取復(fù)雜,速度比內(nèi)存緩存慢。
在內(nèi)存使用率低,緩存小尺寸資源時(shí),會(huì)優(yōu)先使用內(nèi)存緩存;反之,在內(nèi)存使用率高,緩存大尺寸資源時(shí),會(huì)優(yōu)先使用硬盤緩存。
三、緩存規(guī)則
? ? 瀏覽器端和服務(wù)端的緩存規(guī)則,主要在http協(xié)議頭中定義。
? ? 與緩存有關(guān)的http消息報(bào)頭有:Expires,Pragma,Cache-Control,Last-modified,If-Modified-Since,Etag,If-None-Match。
1、強(qiáng)制緩存策略
當(dāng)瀏覽器發(fā)起 HTTP 請求時(shí),會(huì)依次查找上述緩存位置中是否存在緩存資源并通過緩存標(biāo)識(shí)字段 Expires 或 Cache-Control 來驗(yàn)證緩存資源是否過期。
Expires:HTTP 1.0 緩存控制響應(yīng)頭,緩存過期時(shí)間,用來指定資源到期的時(shí)間,是服務(wù)器端的具體的時(shí)間點(diǎn)。
Cache-Control:HTTP 1.1 緩存控制響應(yīng)頭,是服務(wù)器端在響應(yīng)請求時(shí)用來規(guī)定資源是否需要被瀏覽器緩存以及緩存的有效時(shí)間等。
Cache-Control可以出現(xiàn)在request header中,也可以出現(xiàn)在response header中,它有以下幾個(gè)屬性,這些屬性決定了客戶端和服務(wù)端交互時(shí)所采取的緩存策略。
max-age:(單位為s)指定設(shè)置緩存最大的有效時(shí)間,定義的是時(shí)間長短。
no-cache: 指定不緩存響應(yīng),表明資源不進(jìn)行緩存,但是設(shè)置了 no-cache 之后并不代表瀏覽器不緩存,而是在獲取緩存前要向服務(wù)器確認(rèn)資源是否被更改。
no-store:?絕對(duì)禁止緩存。
s-maxage:(單位為s)同max-age,只用于共享緩存(比如CDN緩存)。
public:?指定響應(yīng)會(huì)被緩存,并且在多用戶間共享。
private:?響應(yīng)只作為私有的緩存(見下圖),不能在用戶間共享。如果要求HTTP認(rèn)證,響應(yīng)會(huì)自動(dòng)設(shè)置為 private。
Expires 是 HTTP 1.0 的字段,而 Cache-Control?是 HTTP 1.1 的字段,當(dāng) Expires?與?Cache-Control 同時(shí)存在時(shí),Cache-Control 的優(yōu)先級(jí)要高于?Expires。
若是命中緩存(即存在緩存資源并且緩存資源未過期),則瀏覽器響應(yīng) HTTP Status Code 200,并直接使用緩存資源作為返回結(jié)果,不需要發(fā)起 HTTP 請求;若是存在緩存資源但緩存資源已過期,則進(jìn)入協(xié)商緩存。
2、協(xié)商緩存
Last-modified & If-modified-since
Last-Modified 是服務(wù)器端在響應(yīng)請求時(shí)用來說明資源的最后修改時(shí)間。與之對(duì)應(yīng)的是If-Modified-Since字段,在協(xié)商緩存過程中,瀏覽器發(fā)送的 HTTP 請求中 Header 中會(huì)帶上 If-Modified-Since 字段,值為緩存資源?Last-Modified 屬性的值。
當(dāng)服務(wù)器端接收到帶有?If-Modified-Since 的請求時(shí),則會(huì)將 If-Modified-Since 的值與被請求資源的最后修改時(shí)間做對(duì)比。如果相同,說明資源沒有新的修改,則響應(yīng) HTTP Status Code 304,瀏覽器會(huì)繼續(xù)使用緩存資源;如果最后修改時(shí)間比較新,則說明資源被修改過,則響應(yīng) HTTP Status Code 200,并返回最新的資源。
Etag & & If-None-Match
Etag 是服務(wù)器端在響應(yīng)請求時(shí)用來說明資源在服務(wù)器端的唯一標(biāo)識(shí)。與之對(duì)應(yīng)的是If-None-Match字段,在協(xié)商緩存過程中,瀏覽器發(fā)送的 HTTP 請求中 Header 中會(huì)帶上 If-None-Match 字段,值為該緩存資源?Etag 屬性的值。
當(dāng)服務(wù)器端接收到帶有?If-None-Match 的請求時(shí),則會(huì)將 If-None-Match 的值與被請求資源的唯一標(biāo)識(shí)做對(duì)比。如果相同,說明資源沒有新的修改,則響應(yīng) HTTP Status Code 304,瀏覽器會(huì)繼續(xù)使用緩存資源;如果不同,則說明資源被修改過,則響應(yīng) HTTP Status Code 200,并返回最新的資源。
Last-Modified 是 HTTP 1.0 的字段,而 Etag 是 HTTP 1.1 的字段,當(dāng) Last-Modified 與 Etag 同時(shí)存在時(shí),Etag 的優(yōu)先級(jí)要高于 Last-Modified。
Etag 的出現(xiàn)主要是為了解決 Last-Modified?存在的問題:
Last-Modified 標(biāo)注的最后修改只能精確到秒級(jí),如果某些文件在 1 秒鐘以內(nèi)被修改多次的話,它將不能準(zhǔn)確標(biāo)注文件的最后修改時(shí)間;
如果本地打開緩存文件,即使沒有對(duì)文件進(jìn)行修改,但 Last-Modified 卻改變了,導(dǎo)致文件沒法使用緩存;
參考文章: