瀏覽器的資源請求,若是使用了緩存基本上是兩種狀況css
上面兩種方式有什麼區別呢?簡單地說,第一種方式是不向瀏覽器發送請求,直接使用本地緩存文件。第二種方式,瀏覽器雖然發現了本地有該資源的緩存,可是不肯定是不是最新的,因而想服務器詢問,若服務器認爲瀏覽器的緩存版本還可用,那麼便會返回304。html
那麼,瀏覽器如何決定是使用哪一種方式呢?這就和服務器在請求返回中的Header字段有關了。下面對相關的字段進行簡單介紹。node
Cache-Control 是最重要的規則。這個字段用於指定全部緩存機制在整個請求/響應鏈中必須服從的指令。該字段一般覆蓋默認緩存算法。另外,緩存指令是單向的,即請求中存在一個指令並不意味着響應中將存在同一個指令。git
簡單地說,該字段用於控制瀏覽器在什麼狀況下直接使用本地緩存而不向服務器發送請求。通常具備如下值:github
public
: 全部內容都將被緩存private
: 內容只緩存到似有緩存中no-cache
: 全部內容都不會被緩存no-store
: 全部內容都不會被緩存到緩存或者internet臨時文件中must-revalidation/proxy-revalidation
: 若是緩存的內容失效,請求必須發送到服務器/代理以進行從新驗證max-age=xxx( xxx is numeric )
: 緩存的內容將在 xxx 秒後失效, 這個選項只在HTTP 1.1可用, 並若是和Last-Modified一塊兒使用時, 優先級較高其中最經常使用的屬性即是 max-age
, 這個字段很簡單,就是瀏覽器在資源成功請求後的制定時間內,都將直接調用本地緩存和不會向服務器去請求數據。算法
Expires 頭部字段提供一個日期和時間,在該日期前的全部對該資源的請求都會直接使用瀏覽器緩存而不用向服務器請求(注意:cache-control max-age 和 s-maxage 將覆蓋 Expires 頭部。)apache
Expires 字段接收如下格式的值:「Expires: Sun, 08 Nov 2009 03:37:26 GMT」。瀏覽器
可是使用Expires
存在服務器端時間和瀏覽器時間不一致的問題。緩存
Last-Modified
和E-tag
的做用都是向服務器確認當前緩存文件是否爲最新。拋開功能不看,這兩個字段的表現以下:服務器
Last-Modified
字段,那麼當下一次瀏覽器再一次向服務器請求該資源時(前提是瀏覽器中上一次的資源被緩存過了),會在請求header中包含If-Modified-Since
字段,且值與服務器第一次響應給瀏覽器的Last-Modified
字段一致ETag
字段,那麼當下一次瀏覽器再一次向服務器請求該資源時(前提是瀏覽器中上一次的資源被緩存過了),會在請求header中包含If-None-Match
字段,且值與服務器第一次響應給瀏覽器的ETag
字段一致那麼上述是遵循了Http協議的瀏覽器會自動實現的,而要實現304的功能,就須要服務器(好比Apache對於靜態資源會自動實現這兩個字段的響應)或者咱們手動在服務器端編寫響應的邏輯來實現。
Last-Modified
字段,則說明瀏覽器中包含了該資源的某一版本的緩存,此時服務器端將根據該字段的值進行必定的邏輯判斷,以決定讓瀏覽器直接使用已有的緩存(返回304
)仍是將最新的文件發送過去(200
,發送新文件並更新Last-Modified
字段)If-None-Matc
字段,則說明瀏覽器中包含了該資源的某一版本的緩存,此時服務器端將根據該字段的值進行必定的邏輯判斷,以決定讓瀏覽器直接使用已有的緩存(返回304
)仍是將最新的文件發送過去(200
,發送新文件,並更新ETag
)若同時使用了Last-Modified
和ETag
,正確的作法應該是當二者都符合條件時,才返回304
Etag
主要爲了解決 Last-Modified
沒法解決的一些問題。
md5
)來做爲ETag
If-Modified-Since
能檢查到的粒度是s級的,這種修改沒法判斷(或者說UNIX記錄MTIME只能精確到秒)通常咱們打開(或者更新)一個頁面(或者資源)有幾種方式:
上面幾種方式對資源的請求,會產生不一樣的結果,而且各瀏覽器的表現並不一致。具體的區別能夠參考鳥哥的《瀏覽器緩存機制》
其中你們須要注意的一點是,刷新頁面(F5或者刷新按鈕),不論是否設置了max-age
,都會從新像服務器發送請求。可是這不影響304
邏輯。
用nodejs
寫了一個簡單的靜態文件服務器,用來測試上面的Cache-Control
和Last-Modified
,具體代碼能夠看gist
例子比較簡單,大致邏輯:
200
返回設置max-age=10
,即緩存10秒。同時設置Last-Modified
if-modified-since
字段,則304
測試過程和結果:
index.html
仍是index.css
均爲200
,且response中包含了max-age
和Last-Modified
index.html
爲304
,index.css
爲200 ok ( from cache )
304
(在10s內或者不在10s內)須要注意的問題:
index.html
不論是否設置了max-age
,都是304
,同理,將index.css
直接放到地址欄中請求也是304
index.css
一次304
以後的10s內又能繼續進行不須要請求服務器的直接本地緩存。這裏我我的認爲,瀏覽器的「直接使用本地緩存「的效果和從服務器成功200
到數據產生的效果是一致的,除了文件自己,header字段等信息也是一樣會被cache的,所以304
以後,max-age
又能夠被繼續使用一遍。作了nodejs
的實驗以後,又開啓了apache
服務器,一樣的將index.html
和index.css
文件放置到服務器根目錄中,請求後,發現apache
默認已經作了Last-Modified
和ETag
的處理,而且在修改index.css
文件後,能夠觀察到這兩個值的變化。