說說瀏覽器端緩存的那點事兒-撲朔迷離的 etag 與 last-modified


前言


做為一個正宗的科班出身, 《計算機網(wǎng)絡(luò)》 這門課程肯定是學(xué)過的,但到底有沒有學(xué)細學(xué)透學(xué)明白,就不得而知了。

依舊是做為一個正宗的科班出身偽前端,在新的互聯(lián)網(wǎng)寒冬之下又被某互聯(lián)網(wǎng)公司的面試官噴了。

雖然曾經(jīng)還是比較仔細的看過 HTTP 相關(guān)的東西,但長時間沒有復(fù)習(xí)加上當(dāng)時沒有做筆記、寫博客沉淀還是有很多的生疏。

回去之后查了一下相關(guān)的資料,算是做一次知識的沉淀(造輪子)。


正文


1、 304


打開 Chrome,按下 F12、訪問一個曾經(jīng)訪問過的網(wǎng)頁,如果沒有勾選** Disable cache**,很容易能看到這樣的狀態(tài):


304,代表 NOT MODIFIED,他發(fā)生在這樣的一種狀態(tài)下:服務(wù)器正確接收到了一個帶條件(Conditional Validation)的 GET,如果這個條件是真的就會返回 304、否則就會返回 200(A conditional GET or HEAD request has been received and would have resulted in a 200 OK response if it were not for the fact that the condition evaluated to false)。


換個角度來說,如果瀏覽器接收到的 response 的狀態(tài)碼是 304,就代表這個資源在客戶端中的緩存依然是有效的,即在上次拿到資源到當(dāng)前這段時間之內(nèi)服務(wù)器端并沒有對這個資源做修改。

這樣做有什么好處呢? 顯然這樣可以在使用很小的一個 HTTP 請求的代價上就實現(xiàn)下面兩個功能:

  • 確保拿到的資源是最新的
  • 客戶端資源沒有問題的情況下不需要再次那資源,解決每次完整請求資源時的性能問題。 撒

那所謂的帶提交的 GET 是怎么回事呢? 請看下面的內(nèi)容:

2、 撲所迷離的 etag 與 last-modified


a、曖昧期的表白


在大多數(shù)的情況下大家聽到的可能就是 etag 與 last-modified,沒錯,他就是服務(wù)器在接收到帶條件的GET 請求之后塞到 response 的 header 里面。那條件是什么?是不是又與 etag 和 last-modified 相對應(yīng)呢?

答案是肯定的,他們的對應(yīng)如下所示:

  • etag —— if-none-match
  • last-modified —— if-modified-since

b、前戲


有了上面的對應(yīng)關(guān)系之后相信不再撲朔了。他們的關(guān)系如下:


如果本地有相關(guān)資源的緩存,并且在緩存的時候響應(yīng)頭里面有 etag 或者 last-modified 的情況,這個時候去請求服務(wù)器的時候就會是帶有條件的 GET 請求(Conditional Validation)。


在請求頭里面可能會有兩個字段: if-none-match、 if-modified-since,其中 if-none-match 的值是服務(wù)器上次返回該資源時響應(yīng)頭里面 etag 的值,if-modified-since 的值是服務(wù)器上次返回該資源時響應(yīng)頭里面 last-modified 里的值。


緊接著服務(wù)器端就會接收到這個帶有條件的 request,然后會根據(jù)這兩個值去判斷緩存的資源是否是最新的。


如果沒問題,即資源是最新的情況下就會返回 304,body 為空;不是的話就會返回 200,即目前瀏覽器端的資源不是最新的,body 里面就是資源體,然后客戶端就會用最新返回的資源覆蓋掉之前的資源


也就是說。發(fā)送這種帶條件的請求的必要條件是 資源在瀏覽器端有緩存,并且在緩存的時候服務(wù)器端的reponse 里面有 etag 或者 last-modified。如果這個條件不滿足,發(fā)送的請求就是沒有條件的(unconditionally)。


c、前戲后的協(xié)商 —— 一些優(yōu)化


雖然說通過這種方式能夠減輕服務(wù)器的壓力,解決一些請求資源時的性能問題。但是細細看來,還是存在一些浪費:每個都要去帶上條件請求服務(wù)器來看資源是不是最新的,大多情況下是最新的情況下豈不是每次都在做無意義的驗證? 別急,做個約定就好,在 response 里面加上 Cache-Control 和 Expires 即可。

通常他們是長這樣的:

  • cache-control:max-age=96247433
  • expires:Thu, 03 Jan 2019 04:24:16 GMT

  • Cache-control 用于控制HTTP緩存(在HTTP/1.0中可能部分沒實現(xiàn),僅僅實現(xiàn)了Pragma: no-cache);
  • Expires 表示存在時間,允許客戶端在這個時間之前不去檢查(發(fā)請求),等同 max-age 的效果。
  • 但是如果同時存在,則被 Cache-Control 的 max-age 覆蓋。

題外話:

Expires要求客戶端和服務(wù)端的時鐘嚴格同步。

HTTP1.1引入Cache-Control來克服Expires頭的限制。

如果max-age和Expires同時出現(xiàn),則max-age有更高的優(yōu)先級。


d、前戲后的爭執(zhí)


這么多的字段,現(xiàn)在數(shù)數(shù)好像已經(jīng)有 6 個了,那么他們是誰先誰后?

如果比較粗的說先后順序應(yīng)該是這樣:


  • Cache-Control —— 請求服務(wù)器之前
  • Expires —— 請求服務(wù)器之前
  • If-None-Match (Etag) —— 請求服務(wù)器
  • If-Modified-Since (Last-Modified) —— 請求服務(wù)器

需要注意的是 如果同時有 etag 和 last-modified 存在,在發(fā)送請求的時候會一次性的發(fā)送給服務(wù)器,沒有優(yōu)先級,服務(wù)器會比較這兩個信息(在具體實現(xiàn)上,大多數(shù)做法針對這種情況只會比對 etag)。

服務(wù)器在輸出上,如果輸出了 etag 就沒有必要再輸出 last-modified(實際上大多數(shù)情況會都輸出)。

具體可以參見知乎上的這個問題——關(guān)于瀏覽器的緩存,有了Etag,last-Modified 還有必要存在嗎???。如果要深究,就要仔細看看 RFC 了,如果恰好你看了,歡迎在評論中提出。


e、完事后的討論 – 各種途徑的訪問


瀏覽器輸入 url 之后敲下回車,刷新 F5 與強制刷新(Ctrl + F5),又有什么區(qū)別?


實際上瀏覽器輸入 url 之后敲下回車就是先看本地 cache-control、expires 的情況,刷新(F5)就是忽略先看本地 cache-control、expires 的情況,帶上條件 If-None-Match、If-Modified-Since,強制刷新(Ctrl + F5)就是不帶條件的訪問。


值得注意的是,如果是瀏覽器輸入url之后敲下回車 你在 network 里面看到的狀態(tài)往往是 200,但是大小是 0。這是因為這個 200 是上次訪問資源返回的狀態(tài)碼。

如果你是一位開發(fā)者,還是建議在 Chrome 里面開啟 Disable Cache.


推薦閱讀資料



轉(zhuǎn)自:rccoder-----說說瀏覽器端緩存的那點事兒-撲朔迷離的 etag 與 last-modified

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 淺談瀏覽器Http的緩存機制 ? ? ? ? ? ? ? ? 針對瀏覽器的http緩存的分析也算是老生常談了,每隔...
    meng_philip123閱讀 1,127評論 0 10
  • 針對瀏覽器的http緩存的分析也算是老生常談了,每隔一段時間就會冒出一篇不錯的文章,其原理也是各大公司面試時幾乎必...
    全端玩法閱讀 965評論 0 9
  • 針對瀏覽器的http緩存的分析也算是老生常談了,每隔一段時間就會冒出一篇不錯的文章,其原理也是各大公司面試時幾乎必...
    單純的土豆閱讀 479評論 0 2
  • 轉(zhuǎn)載:瀏覽器緩存知識小結(jié)及應(yīng)用 閱讀目錄 1. 瀏覽器緩存基本認識 2. 強緩存的原理 3. 強緩存的管理 4. ...
    meng_philip123閱讀 1,167評論 4 18
  • 多年以后 為什么,經(jīng)過多年以后,所有的過與錯,無法解脫? 不知道為什么,突然哼起這首傷感的歌…… 多年以后,當(dāng)你回...
    蘇再蓉閱讀 366評論 0 1

友情鏈接更多精彩內(nèi)容