淺談瀏覽器緩存機制及不一樣刷新行爲對它的影響

測試同窗:你問題改了嘛?我怎麼沒看到效果啊?前端

前端同窗:我改了啊,可能有緩存吧,清一下緩存試試(心裏os:難道是我寫的代碼有問題?🤔🤔🤔)。nginx

首先說下爲何須要緩存?面試

如今的前端頁面已經不是刀耕火種時代的效果了,隨便打開一個頁面都能看到各類炫酷的交互效果。像如今各類電商的促銷活動:618,雙11,雙12🛒🛒🛒。每個活動對於服務器都是一個巨大的挑戰,就拿一個圖片來講,若是每一個用戶每次訪問這個頁面都要去服務器拿新的資源的話,服務器應該早就崩潰了😵😵😵。chrome

咱們主要來討論下瀏覽器的緩存機制,它同時也是前端面試中必問的一道題。

瀏覽器的緩存機制

瀏覽器的緩存主要是遵循http緩存機制,主要分爲兩種緩存:瀏覽器

  • 強緩存
  • 協商緩存(也叫對比緩存)

強緩存

強緩存包括:Pragma,Expires,Cache-Control緩存

首先解釋下什麼是強緩存bash

強緩存是表明瀏覽器進行一次請求後,把請求的文件放在內存或者硬盤中,有的時候咱們會在狀態碼中看到from memory cache或者from disk cache,這時候其實表明咱們命中了強緩存,此時並無發生瀏覽器發送請求的行爲。服務器

memory cache 跟disk cache的區別測試

  • memory cache 是把資源緩存到內存中,當進程退出時,內存中的數據會被清空,下次訪問須要執行別的緩存策略(一個瀏覽器的標籤頁至關於一個進程)
  • disk cache 是把資源緩存在磁盤中,進程退出時不受影響,下次訪問能夠繼續執行這次緩存策略

Pragma

現代瀏覽器通常都是基於HTTP/1.1的。 因爲 Pragma 在 HTTP 響應中的行爲沒有確切規範,因此不能可靠替代 HTTP/1.1 中通用首部 Cache-Control,儘管在請求中,假如 Cache-Control 不存在的話,它的行爲與 Cache-Control: no-cache 一致,建議只在須要兼容 HTTP/1.0 客戶端的場合下應用 Pragma 首部。網站

Pragma: no-cache
複製代碼

做用是強制要求緩存服務器在返回緩存的版本以前將請求提交到源頭服務器進行驗證。

Expires

先來看下它的設置參數:

expires:10s/10m/10h/10d; //分別對應:秒,分,時,天
複製代碼

Expires的值爲服務器返回的規定該資源的到期時間,在下一次瀏覽器請求時會拿本地時間對比這個服務器返回的時間,若是沒有過時則直接可使用緩存數據,無需再發起請求。

這時候問題來了,本地的時間是能夠修改的

一方面對比的是本地的時間會有必定的偏差;另外一方面如今瀏覽器基本都是基於http1.1版本的,Expires是http1.0版本的產物,這個時候就出現了它的替代品Cache-Control。

Cache-Control

咱們先來看下它的經常使用參數都有哪些:

參數 含義
max-age 單位是秒,失效的時間
no-cache 強制要求緩存把請求提交給原始服務器進行驗證
no-store 緩存不該存儲有關客戶端請求或服務器響應的任何內容
public 存在響應頭中,表示能夠被任何對象緩存
private 存在響應頭中,表示只能被單個用戶緩存,不能做爲共享緩存

指令不區分大小寫,多個指令以逗號分隔,Cache-Control比Expires的優先級要高

no-cache跟no-store傻傻分不清楚

首先cache-control是一個通用消息頭字段,就是說請求頭跟響應頭均可以加入這個字段,可是在不一樣的位置意思是不一樣的:

  • 請求頭中的no-cache表明每次都去請求新的資源,跳過全部類型的緩存。
  • 響應頭中的no-cache表明每次都要去服務器驗證緩存是否過時,跳過強緩存。
  • no-store表明禁用一切緩存。
  • 另外說一下max-age=0,表明每次都要去服務器驗證緩存是否過時,跳過強緩存。

協商緩存(對比緩存)

協商緩存包括:Last-Modified/If-Modified-Since,Etag/If-None-Match

什麼叫協商緩存?

當瀏覽器檢查強緩存過時後,因而發送請求到服務器,這時候服務器並不會直接去拿新的資源,而是要檢查請求頭部是否有緩存標識If-Modified-Since或者If-None-Match,判斷成功後則返回304 Not Modified,通知客戶端可使用緩存的數據。

對於協商緩存,在相對高的nginx版本里面,會自動給客戶端返回Last-Modified跟Etag。客戶端在下次請求一樣的url時,根據HTTP協議的規定,會帶上If-Modified-Since報頭,值爲上次服務器返回的Last-Modified值;同時也會帶一個If-None-Match報頭,值爲上次服務器返回的Etag值。咱們能夠在Response Headers 跟 Request Headers 中查看參數。

Last-Modified/If-Modified-Since

Last-Modified是存在於響應頭部,包含源頭服務器認定的資源作出修改的日期及時間。它一般被用做一個驗證器來判斷接收到的或者存儲的資源是否彼此一致。相對應的If-Modified-Since存在於請求頭部,它的值是上一次服務器返回的Last-Modified的值。

請求頭:

響應頭:

Etag/If-None-Match

Etag存在於響應頭部的,是服務器資源的惟一標識符,至關於文件指紋,若是文件改變則這個值就會改變。相對應的If-Modified-Since存在於請求頭部,它的值是上一次服務器返回的Etag的值。

請求頭:

響應頭:

有Last-Modified爲何還須要Etag?

  • Last-Modified精確度只到的級別,若是遇到短期內頻繁改動的資源修改操做則失效
  • 有時候可能會出現某些文件會被定時生成,其實內容都是同樣的,可是最後修改時間卻改變了,則命中緩存失效
  • 可能存在服務器不能獲取準確的文件修改時間的狀況,集羣服務器上各個服務器上的文件時間可能不一樣

用戶的刷新行爲對緩存的影響

此處描述的是mac下的chrome,針對具體資源去訪問的結果,每一個版本的瀏覽器可能存在不一樣。

行爲一:

瀏覽器新開窗口的輸入url進行訪問,先檢查強緩存,若是命中Status Code會顯示 200 OK (from disk cache)或者200 OK (from memory cache)

行爲二:

地址回車或者正常從新加載(command + r)會致使瀏覽器跳過檢查強緩存,直接去服務器檢查協商緩存,若是命中則Status Code會顯示304 Not Modified

行爲三:

硬性的從新加載行爲(command + shift + r)會致使瀏覽器跳過強緩存跟協商緩存,直接去請求新的資源文件,返回狀態碼200。

行爲四:

清空緩存並硬性從新加載。會致使瀏覽器把緩存清空掉,直接去請求資源,返回狀態碼200。

若是是對一個站點的訪問,頁面裏面包括靜態資源,則對這種靜態資源來講上述行爲一跟行爲二都先檢查強緩存再去檢查協商緩存,其餘行爲表現一致。

  • 對單個資源的訪問:網上隨便找一張圖片地址放在瀏覽器url裏面進行訪問測試。
  • 對站點的訪問:隨便訪問一個有靜態資源的網站進行訪問測試。

說一下控制檯中的Network選項下面的Disable cache選項

咱們都知道勾選中以後起到不使用緩存的效果,可是其實這個時候,並非把緩存刪掉了,而是選擇讓瀏覽器跳過全部的緩存策略,這時候瀏覽器會在請求頭上加一個參數:Cache-Control:no-cache。若是把這個選項再放開的話仍是會應用緩存策略的,只不過針對具體資源的請求時,瀏覽器會選擇在請求頭部加上Cache-Control:max-age=0來跳過強緩存,檢查協商緩存。

另外說一下判斷瀏覽器有沒有發送請求的方法,能夠看下控制檯的Waterfall部分:

圖中標紅的 request sent指的是發送HTTP請求的時間,若是 值爲零或者是沒有這個字段,則表明沒有發送請求。

有時間再講解一下其餘字段的意思吧,謝謝!!⛽️⛽️⛽️

相關文章
相關標籤/搜索