前端-web緩存

爲什麼需要緩存

本文重點介紹瀏覽器緩存,服務端等緩存不是本文重點

 

首先從原始的前端開發講起,上圖是一個“可愛”的index.html頁面和它的樣式文件a.css,用文本編輯器寫代碼,無需編譯,本地預覽,確認OK,丟到服務器,等待用戶訪問。前端就是這麼簡單,好好玩啊,門檻好低啊,分分鐘學會有木有!


然後我們訪問頁面,看到效果,再查看一下網絡請求,200!不錯,太™完美了!那麼,研發完成。。。。了麼?等等,這還沒完呢!對於大公司來說,那些變態的訪問量和性能指標,將會讓前端一點也不“好玩”。看看那個a.css的請求吧,如果每次用戶訪問頁面都要加載,是不是很影響性能,很浪費帶寬啊,我們希望最好這樣


利用304,讓瀏覽器使用本地緩存。但,這樣也就夠了嗎?不成!304叫協商緩存,這玩意還是要和服務器通信一次,我們的優化級別是變態級,所以必須徹底滅掉這個請求,變成這樣:


強制瀏覽器使用本地緩存(cache-control/expires),不要和服務器通信。好了,請求方面的優化已經達到變態級別,那問題來了:你都不讓瀏覽器發資源請求了,這緩存咋更新?以百度和bing的首頁爲例,index.html也就是入口地址要禁止緩存,然後通過更新頁面中引用的資源路徑,讓瀏覽器主動放棄緩存,加載新資源。如何更改引用資源路徑不是本文重點,感興趣的童鞋可以自行查閱資料,以後我也會更新。

 

 

協商緩存和強緩存

  • 強緩存:瀏覽器在加載資源時,先根據這個資源的一些http header判斷它是否命中強緩存,強緩存如果命中,瀏覽器直接從自己的緩存中讀取資源,不會發請求到服務器。比如某個css文件,如果瀏覽器在加載它所在的網頁時,這個css文件的緩存配置命中了強緩存,瀏覽器就直接從緩存中加載這個css,不會發送請求到服務器,也就是上圖中的from memory cache,谷歌瀏覽器是個特殊的存在,有from memory cache和from disk cache,(假設你已經使用過百度,以百度首頁爲例)當你關閉瀏覽器,再次打開進入百度首頁時,會觸發from disk cache,此時刷新瀏覽器,會觸發from memory cache,此時內容已經加載到瀏覽器內存中,谷歌瀏覽器選擇直接從內存中讀取

     

    disk cache

     

    memory cache

  • 協商緩存:當強緩存沒有命中的時候,瀏覽器一定會發送一個請求到服務器,服務器端依據資源的另外一些http header驗證這個資源是否命中協商緩存,如果協商緩存命中,服務器會將這個請求返回(304),但是不會返回這個資源的數據,而是告訴客戶端可以直接從緩存中加載這個資源,於是瀏覽器就又會從自己的緩存中去加載這個資源;若未命中請求,則將資源返回客戶端,並更新本地緩存數據(200)。

強緩存與協商緩存區別:強緩存不會發請求到服務器,協商緩存會發請求到服務器。

設置緩存

  • HTML Meta標籤控制緩存(非HTTP協議定義)
    <META HTTP-EQUIV="Pragma" CONTENT="no-cache">等等
    上述代碼的作用是告訴瀏覽器當前頁面不被緩存,每次訪問都需要去服務器拉取。這種方法使用上很簡單,但只有部分瀏覽器可以支持,而且所有緩存代理服務器都不支持,因爲代理不解析HTML內容本身。
  • HTTP頭信息控制緩存
    HTTP頭信息控制緩存是通過Expires(強緩存)、Cache-control(強緩存)、Last-Modified/If-Modified-Since(協商緩存)、Etag/If-None-Match(協商緩存)實現,下面詳細介紹。

expires

Expires是http1.0提出的一個表示資源過期時間的header,它描述的是一個絕對時間,由服務器返回,用GMT格式的字符串表示,如:Expires:Thu, 31 Dec 2016 23:55:55 GMT
讀取緩存數據條件:緩存過期時間(服務器)< 當前時間(客戶端)
缺點:Expires是較老的強緩存管理header,由於它是服務器返回的一個絕對時間,這樣存在一個問題,如果客戶端的時間與服務器的時間相差很大(比如時鐘不同步,或者跨時區),那麼誤差就很大,所以在HTTP 1.1版開始,使用Cache-Control: max-age=秒替代。

cache-control

Cache-Control描述的是一個相對時間,在進行緩存命中的時候,都是利用客戶端時間進行判斷,所以相比較Expires,Cache-Control的緩存管理更有效,安全一些。
讀取緩存數據條件:上次緩存時間(客戶端)+max-age < 當前時間(客戶端)
Cache-Control值可以是public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age

各個消息中的指令含義如下:
Public指示響應可被任何緩存區緩存。
Private指示對於單個用戶的整個或部分響應消息,不能被共享緩存處理。這允許服務器僅僅描述當前用戶的部分響應消息,此響應消息對於其他用戶的請求無效。
no-cache指示請求或響應消息不能緩存,該選項並不是說可以設置”不緩存“,而是需要和服務器確認
no-store在請求消息中發送將使得請求和響應消息都不使用緩存,完全不存下來。
max-age指示客戶機可以接收生存期不大於指定時間(以秒爲單位)的響應。上次緩存時間(客戶端的)+max-age(64200s)<客戶端當前時間
min-fresh指示客戶機可以接收響應時間小於當前時間加上指定時間的響應。
max-stale指示客戶機可以接收超出超時期間的響應消息。如果指定max-stale消息的值,那麼客戶機可以接收超出超時期指定值之內的響應消息。
注意:這兩個header可以只啓用一個,也可以同時啓用,當response header中,Expires和Cache-Control同時存在時,Cache-Control優先級高於Expires

Last-Modified/If-Modified-Since

Last-Modified/If-Modified-Since要配合Cache-Control使用。
Last-Modified:標示這個響應資源的最後修改時間。web服務器在響應請求時,告訴瀏覽器資源的最後修改時間。
If-Modified-Since:當資源過期時(強緩存失效),發現資源具有Last-Modified聲明,則再次向web服務器請求時帶上頭 If-Modified-Since,表示請求時間。web服務器收到請求後發現有頭If-Modified-Since 則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說明資源又被改動過,則響應整片資源內容(寫在響應消息包體內),HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應HTTP 304 (無需包體,節省瀏覽),告知瀏覽器繼續使用所保存的cache。
缺點:

  • Last-Modified標註的最後修改只能精確到秒級,如果某些文件在1秒鐘以內,被修改多次的話,它將不能準確標註文件的修改時間(無法及時更新文件)
  • 如果某些文件會被定期生成,當有時內容並沒有任何變化,但Last-Modified卻改變了,導致文件沒法使用緩存,有可能存在服務器沒有準確獲取文件修改時間,或者與代理服務器時間不一致等情形(無法使用緩存)。

Etag/If-None-Match

爲了解決Last-Modified的問題,HTTP1.1中引入了Etag,Etag/If-None-Match也要配合Cache-Control使用
Etag:web服務器響應請求時,告訴瀏覽器當前資源在服務器的唯一標識(生成規則由服務器決定)。Apache中,ETag的值,默認是對文件的索引節(INode),大小(Size)和最後修改時間(MTime)進行Hash後得到的。
If-None-Match:當資源過期時(使用Cache-Control標識的max-age),發現資源具有Etage聲明,則再次向web服務器請求時帶上頭If-None-Match (Etag的值)。web服務器收到請求後發現有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決定返回200或304。
Etag是服務器自動生成或者由開發者生成的對應資源在服務器端的唯一標識符,能夠更加準確的控制緩存。Last-Modified與ETag一起使用時,服務器會優先驗證ETag。

大廠的緩存設置

以百度和必應爲例,百度同時使用了expires和cache control,etag和Last-Modified,而必應只使用了cache-control,Last-Modified。
使用時,可以根據自己的場景設置。

 

百度首頁

 

必應首頁

用戶行爲與緩存

用戶操作 Expires/Cache Control Last-Modified/Etag
地址欄回車 有效 有效
頁面鏈接跳轉 有效 有效
新開窗口 有效 有效
前進/後退 有效 有效
F5/按鈕刷新 無效,瀏覽器重置max-age=0 有效
Ctrl+F5 無效重置cache-control: no-cache 無效,請求頭丟棄該選項

然而上表並不完全準確,比如谷歌chrome這個神奇的存在,筆者使用的66版本,F5刷新,並不會重置max-age=0,依然命中強緩存,但是linux中使用的chrome 50版本則會重置max-age=0

 

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