瀏覽器緩存HTTP緩存的細節補充和探討

最近在掘金上看到一篇講解HTTP緩存的文章《前端優化:瀏覽器緩存技術介紹》,我覺得講得很好,如果大家不熟悉HTTP緩存的話可以先看下這篇博客,很多細節都講的很具體,向博主學習!
看完後感覺有幾個細節博主可能沒有展開,引起了疑問和好奇,我查了下資料把疑問分享給大家,也提了一些問題,希望有高手大佬幫忙解答,有想法歡迎指出一起探討。

疑問1:如果不啓用強緩存的話,協商緩存根本沒有意義,這個該怎麼理解呢?博客原文爲:


相信有小夥伴和我一樣,第一反應一頭霧水,其實這句的描述不是很貼切,原因是作者沒有講Cache-Control的幾個可選值的含義,配合起來講解就很容易理解了。
對於強緩存來說,Cache-Control 是最重要的規則。常見的取值有private、public、no-cache、max-age,no-store,默認爲private。
private: 只有瀏覽器可以緩存,(默認)
public: 可以被任何緩存區緩存,包括瀏覽器和代理服務器
max-age=xxx: 緩存的內容將在 xxx 秒後失效
no-cache: 需要使用協商緩存來驗證緩存數據
no-store: 所有內容都不會緩存,強制緩存,協商緩存都不會觸發
其中,max-age=xxx並不是獨立的屬性,如你設置了Cache-Control:max-age=1800,等價於Cache-Control:private, max-age=1800,你也可以設置成Cache-Control:public, max-age=1800,所以當你想要每次請求都去詢問服務器對比一下,設置Cache-Control:no-cache或者Cache-Control:no-cache, max-age=0就可以,現在看來Cache-Control也是用來控制協商緩存的。Cache-Control是緩存的總開關,作者把Cache-Control看做是強緩存的屬性,所以纔會出現如果不啓用強緩存的話,協商緩存根本沒有意義的描述。

問題1:如果我設置了Cache-Control:private或者Cache-Control:public,但沒有設置max-age,那麼第一次從服務器下載緩存起來的文件有默認效期嗎?有的話是多長呢?有答案的小夥伴求評論區告知。

疑問2:Etag / If-None-Match貌似平白無故多出一次tag計算,它比Last-Modified / If-Modified-Since 好在哪兒?

大家知道,ETag規範比Last-Modified規範出的晚,說明ETag一定是在Last-Modified存在某些缺陷短板才應運而生的。一種普遍的ETag算法是取文件的特徵值計算Hash(比如md5)。Etag 主要爲了解決 Last-Modified 無法解決的一些問題:
1)、有時候有些文件的內容不會改變,但是文件的元數據卻經常改變,(比如創建日期、創建作者這些),這個時候服務器並不希望瀏覽器認爲這個文件被修改了,而重新下載一次;
2)、有時候有些文件修改的頻率非常高,幾毫秒就修改一次,If-Modified-Since 的粒度是秒級的,這種頻率無法被察覺(也有人說UNIX操作系統記錄MTIME只能精確到秒);
3)、某些服務器不能精確的得到文件的最後修改時間。
也就是說文件的最後修改時間變了不能100%說明文件內容變了,文件內容變了也不能100%體現在最後修改時間,用文件的最後修改時間來表示文件發生修改並不可靠所以纔有了ETag。
看起來ETag已經完全可以替代Last-Modified了,而且我心裏也是這麼想的,可以網上的聲音卻不一樣。我這裏彙總一下:

說法1:有的地方說Etag / If-None-Match的優先級高於Last-Modified / If-Modified-Since。但ETag不是Last-Modified的替代,你得根據你程序的特點選擇一個適合的使用。

如果瀏覽器的Request Header裏If-None-Match和If-Modified-Since兩個都存在,服務器會只處理If-None-Match,如果服務器算出來的ETag跟If-None-Match不一樣會直接返回新的文件和新的ETag,If-Modified-Since就被忽略了,如果算出來ETag跟If-None-Match一樣,就直接返回304,不會再去判斷If-Modified-Since了。

說法2:如果 Last-Modified 和 ETag 同時被使用,則要求它們的驗證都必須通過纔會返回304,若其中某個驗證沒通過,則服務器會按常規返回資源實體及200狀態碼。nginx默認是兩則都開啓的。

作者引用的文章《 [淺談瀏覽器http的緩存機制]》裏就是這種觀點。

那麼問題來了:
1、文件的Hash本身足以說明文件是否發生修改,是可靠結論,爲啥還要繼續判斷 Last-Modified呢?
2、如果爲了解決Last-Modified有時難以察覺文件變化才使用ETag,不應該Last-Modified優先級高於ETag嗎?Last-Modified發生變化就直接返回200,沒變化或者獲取不到再判斷ETag?
3、實在模擬不出文件內容變了,最後修改時間沒變的情形,無法驗證“如果 Last-Modified 和 ETag 同時被使用,則要求它們的驗證都必須通過纔會返回304”,是否正確。各位大佬幫忙支支招

問題3:爲啥讀緩存時from memory cache ,from disk cache會有兩個,什麼時候from memory 什麼時候from disk呢?

from memory cache是指從瀏覽器緩存讀文件,進程死了,文件就沒了。
from disk cache是指從PC本地磁盤讀文件,進程死了,磁盤文件還在。
那麼這個事就和服務器沒關係了,也不是標準規範,純屬瀏覽器個人行爲。所以各家瀏覽器的表現還不一樣,比如firefox瀏覽器就只有from memory cache,沒有from disk cache,它不會把文件備份到磁盤。
from disk cache多見於chrome,據瞭解chrome在訪問一個新域名的網站時,會把新下載的文件的一部分(包括css、js)備份一份到磁盤,下一次如果命中強緩存的話,先從磁盤讀取文件,磁盤裏沒有再去瀏覽器緩存裏讀,如果都沒有再問服務器要。但是先從瀏覽器緩存讀不比磁盤快嗎?原因我認爲是:chrome不想給用戶造成“喫內存”的現象,把一些他們認爲可以存磁盤的文件塞到磁盤了(也有可能是瀏覽器緩存只開闢固定空間,放不下了再塞到磁盤,所以看上去有的js放在了瀏覽器緩存,有的js又放在磁盤,抓不到規律),當磁盤文件的數量遠遠大於瀏覽器緩存數量,索性先讀磁盤來得更直接一些。比如我用chrome隨便打開一個頁面,刷新下看到from disk cache的數量還是要多一些的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章