前端客戶端緩存相關的總結

這裏主要記錄在平常中對知識的學習,經過結合筆記與自身理解的方式嘗試寫下總結
文章對細節可能不會一一介紹解釋,內容僅做參考
複製代碼

前些日子在面試的時候被問到有關前端優化的,其中回答了利用前端緩存,接着就被追問有關緩存的一些問題,但回答得不是很好,有必要再整理理解一下。因爲目前只查閱了有關客戶端緩存相關的知識,因此接下來內容都是圍繞着它來說。固然了,其餘方式的緩存也是要學習的javascript

1、緩存的分類

平時中通常說的都是客戶端緩存,固然啦,還有其餘類別的。此處提供瞭解:html

  • CDN緩存
  • DNS緩存
  • 客戶端緩存
  • Service Worker與緩存及離線緩存
  • PageCache與ajax緩存

2、緩存的做用

使用緩存有以下優化:前端

  • 減小冗餘的數據傳輸
  • 節省網絡費用,緩解網絡瓶頸問題
  • 下降對原始服務器的要求,服務器能夠更快響應,避免出現過載

緩存有時候也可能會帶來不想要的結果,好比使用了緩存的數據致使沒法實時呈現效果
也不能說是好壞,能夠當成一個工具,想發揮什麼樣的做用,關鍵是看咱們怎麼使用它java

3、客戶端緩存

客戶端緩存方式主要分爲強緩存協商緩存兩種面試

  • 強緩存:將資源緩存到本地。再次請求時,直接使用本地的緩存(不用跟服務器進行通訊)
  • 協商緩存:緩存資源到本地並保存該資源的緩存信息。再次請求時,將資源相關信息返回給服務器,讓服務器判斷瀏覽器是否能直接使用本地緩存(整個過程至少與服務器通訊一次)
    • 若是能,直接使用本地的緩存
    • 若是不能,再次請求服務器獲取最新的資源

客戶端緩存操做過程以下:ajax

1.瀏覽器首次請求資源:後端

  • 本地無資源,向服務器獲取對應數據
  • 在獲取到資源後,會根據 響應的header內容 來決定緩存該資源的方式(是否緩存,要緩存的話是使用強緩存仍是協商緩存)

2.瀏覽器後續請求資源:api

  • 先獲取該資源緩存的header信息,判斷是否命中緩存(根據cache-controlexpires信息判斷),若命中,直接從緩存中獲取資源信息,包括緩存header信息。本次請求不會與服務器進行通訊 (強緩存)
  • 若是沒有命中強緩存,瀏覽器會發送請求到服務器,請求會攜帶第一次請求返回的有關緩存的header字段信息(Last-Modified/If-Modified-Since和Etag/If-None-Match),由服務器根據請求中的相關header信息來比對結果是否緩存命中,若命中則服務器返回新的響應header信息更新緩存中的對應header信息,可是並不返回資源內容,它會告知瀏覽器能夠直接從緩存獲取 (協商緩存)
  • 不然從服務器獲取最新的資源內容

能夠用圖來更具體地說明一下:瀏覽器

瀏覽器首次請求資源 緩存

瀏覽器後續請求資源

4、強緩存

與強緩存主要相關的header字段有expirescache-control:max-age=number。而且若是cache-control與expires同時存在的話,cache-control的優先級高於expires

  • expires:這是http1.0時的規範,它的值爲一個絕對時間的GMT格式的時間字符串,如Tue May 14 2019 00:00:10 GMT,若是獲取時間在expires以前,本地緩存有效,反之過時
  • cache-control:max-age=number:這是http1.1時出現的header信息,主要是利用該字段的max-age值來進行判斷,它是一個時間相對值。資源第一次的請求時間和Cache-Control設定的有效期時間,計算出一個資源過時時間。經過這個過時時間跟當前的請求時間比較,若是請求時間在過時時間以前,本地緩存有效,反之過時。cache-control除了該字段外,還有下面幾個比較經常使用的設置值:
    • 1)no-cache:不使用本地緩存
    • 2)no-store:直接禁止遊覽器緩存數據,每次用戶請求該資源,都會向服務器發送一個請求,每次都會下載完整的資源
    • 3)public:能夠被全部的用戶緩存,包括終端用戶和CDN等中間代理服務器
    • 4)private:只能被終端用戶的瀏覽器緩存,不容許CDN等中繼緩存服務器對其緩存

5、協商緩存

與協商緩存相關的header字段有Last-Modified/If-Modified-SinceEtag/If-None-Match
協商緩存是由服務器來肯定緩存資源是否可用的,因此客戶端與服務器端要經過某種標識來進行通訊,從而讓服務器判斷請求資源是否能夠緩存訪問,這主要涉及到上面兩組header字段,這兩組搭檔都是成對出現的
即第一次請求的響應頭帶上某個字段(Last-Modified或者Etag),則後續請求則會帶上對應的請求字段(If-Modified-Since或者If-None-Match),若響應頭沒有Last-Modified或者Etag字段,則請求頭也不會有對應的字段

  • Last-Modified/If-Modified-Since: 兩者的值都是GMT格式的時間字符串,具體過程:
    • 1)瀏覽器第一次跟服務器請求一個資源,服務器在返回這個資源的同時,在respone的header加上Last-Modified的header,這個header表示這個資源在服務器上的最後修改時間
    • 2)瀏覽器再次跟服務器請求這個資源時,在request的header上加上If-Modified-Since的header,這個header的值就是上一次請求時返回的Last-Modified的值
    • 3)服務器再次收到資源請求時,根據瀏覽器傳過來If-Modified-Since和資源在服務器上的最後修改時間判斷資源是否有變化,若是沒有變化則返回304 Not Modified,可是不會返回資源內容;若是有變化,就正常返回資源內容。當服務器返回304 Not Modified的響應時,response header中不會再添加Last-Modified的header,由於既然資源沒有變化,那麼Last-Modified也就不會改變,這是服務器返回304時的response header
    • 4)瀏覽器收到304的響應後,就會從緩存中加載資源
    • 5)若是協商緩存沒有命中,瀏覽器直接從服務器加載資源時,Last-Modified的Header在從新加載的時候會被更新,下次請求時,If-Modified-Since會啓用上次返回的Last-Modified值
  • Etag/If-None-Match: 這兩個值是由服務器生成的每一個資源的惟一標識字符串,當資源有變化時,這個值就會改變;其判斷過程與Last-Modified/If-Modified-Since相似,與Last-Modified不同的是,當服務器返回304 Not Modified的響應時,因爲ETag從新生成過,response header中還會把這個ETag返回,即便這個ETag跟以前的沒有變化

Last-Modified和Etag的區別 在描述中對於Last-Modified和Etag的使用能夠說是差很少的,可是,Etag(http1.1)的出現是爲了解決幾個Last-Modified比較難解決的問題:

  • 一些文件也許會週期性的更改,可是他的內容並不改變(僅僅改變的修改時間),這個時候咱們並不但願客戶端認爲這個文件被修改了,而從新GET
  • 某些文件修改很是頻繁,好比在秒如下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改沒法判斷(或者說UNIX記錄MTIME只能精確到秒)
  • 某些服務器不能精確的獲得文件的最後修改時間 這時,利用Etag可以更加準確的控制緩存,由於Etag是服務器自動生成或者由開發者生成的對應資源在服務器端的惟一標識符

Last-Modified與ETag是能夠一塊兒使用的,服務器會優先驗證ETag,一致的狀況下,纔會繼續比對Last-Modified,最後才決定是否返回304

6、強緩存和協商緩存的區別

7、緩存位置

緩存的位置大體分爲如下三類:Service Worker,Memory Cache,Disk Cache 而且它們的優先級就是按照這個順序,從前日後尋找,找到即返回;找不到則繼續。若最後資源在這些地方都沒有找到的話,再去服務器請求資源

  • service worker
    用戶自定義緩存哪些資源到硬盤上,什麼狀況下使用緩存(路由匹配規則),緩存匹配並返回
    清空緩存的狀況分兩種:一是手動調用api,二是容量超過限制,被瀏覽器清除
    這種方式緩存的資源查看方式:開發者工具 -> Application -> Cache Storage
    當資源請求被髮起的時候,瀏覽器首先從service worker中查找資源,若是緩存爲命中,通常狀況會使用fetch()方法繼續獲取資源,這時瀏覽器就去memory cache 或disk cache中進行下一次找緩存的工做
    特別注意:通過fetch()方法獲取的資源,都會顯示 from ServiceWorker,無論資源實際狀況是從memory cache 或disk cache,仍是從網絡從新請求獲取的

  • memory cache
    內存中的緩存,幾乎全部的網絡請求資源都會被瀏覽器自動加入到memory cache中,被短時間存儲,關閉瀏覽器窗口後memory cache就失效了
    從memory cache中獲取緩存內容的時候,瀏覽器會忽視例如max-age=0,no-cache等頭部配置
    但若是頭部配置設置了no-store,那麼資源就不會進入memory-cache

  • disk cache
    硬盤上的緩存,持久存儲,容許相同資源跨回話跨站點的使用
    嚴格根據HTTP頭部字段斷定該緩存哪些資源,哪些資源可用,以及哪些資源過時了須要從新請求
    當請求命中緩存時,就從硬盤中讀取資源。絕大多數的緩存都來自disk cache

查詢諮詢來源:

  • Chrome開發工具 -> network -> 查看size那一列的值

  • xxk:網絡請求

  • form memory cache

  • disk cache

  • from ServiceWorker

8、不緩存的方式

  1. meta設置
<META HTTP-EQUIV="pragma" CONTENT="no-cache"> 
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate"> 
<META HTTP-EQUIV="expires" CONTENT="0">
複製代碼
  1. ajax請求中的請求頭加入取消緩存設置
If-Modified-Since: 0
Cache-Control: no-cache
複製代碼
  1. ajax請求url後加入隨機數或時間戳參數
url + ? ran = Math.random()/new Date().getTime()
複製代碼
  1. 後端返回響應頭相關參數設置
相關文章
相關標籤/搜索