【HTTP緩存】瀏覽器緩存理論知識

時間:2016-12-12 17:51:30
做者: zhongxiahtml

零、前言

這裏主要寫的是理論,具體實踐的比較少,後期寫一個實踐教程,內容基本都是從參考文章裏面抄過來的【看完文章,順便寫作下筆記,加深理解。】前端

瀏覽器緩存,也就是客戶端緩存,既是網頁性能優化裏面靜態資源相關優化的一大利器,也是無數web開發人員在工做過程不可避免的一大問題,因此在產品開發的時候咱們老是想辦法避免緩存產生,而在產品發佈之時又在想策略管理緩存提高網頁的訪問速度。java

瞭解瀏覽器的緩存命中原理,是開發web應用的基礎,本文着眼於此,學習瀏覽器緩存的相關知識,總結緩存避免和緩存管理的方法,結合具體的場景說明緩存的相關問題。但願能對有須要的人有所幫助。nginx

1、瀏覽器緩存基本認識

1. 強緩存 和 協商緩存

瀏覽器在加載資源的時,先根據 http header 判斷它是否命中強緩存.web

  • 命中強緩存:瀏覽器直接從本身緩存中讀取資源,不發送請求到服務器apache

  • 不命中強緩存:瀏覽器發送一個請求到服務器,服務器根據資源的另一些 http header 驗證 該資源 是否命中 協商緩存
    • 命中協商緩存:將請求返回,但不是返回該資源的數據,而是告訴瀏覽器能夠直接從緩存中加載這個資源。後端

    • 不命中協商緩存:服務器返回該資源數據瀏覽器

2. 異同點 和 關係

共同點:命中,都是從瀏覽器緩存中加載資源
不一樣點:強緩存不發送請求到服務器,協商緩存會發送請求。緩存

必須開啓強緩存,協商緩存纔會起做用性能優化

2、強緩存原理

什麼是協商緩存?
如圖,返回http狀態爲200,size爲 form cache 的就是強緩存

1. HTTP Response Header 看強緩存

Expires

HTTP1.0 時代,Expires 【表示資源過時時間】【緩存過時的下一個時間 必須GMT 格式】

可能存在問題:服務器時間和客戶端時間不一致,所以 HTTP1.1 出了一些 Cache-control

如圖:

Cache-control

HTTP1.1 時代,Cache-control: 過時時間【緩存多少毫秒】
如圖:

例子:

Expires步驟

  1. 瀏覽器第一次請求資源,服務器在返回的同時,會在 response 的 header 上加上 Expires

  2. 瀏覽器收到資源後,把資源和 Expires 一塊兒緩存下來

  3. 第二次請求資源時,拿出Expires和當前請求時間比較下,若是還未過時,則直接從緩存中讀取出來,【這個就叫命中緩存

  4. 沒有命中的話,去服務端請求,走協商緩存道路,最後返回時,會返回一個新的 Expires , 瀏覽器在緩存下來。

Cache-control 步驟

和 Expires同樣,只是 過時時間=當前時間+Cache-control 的 Max-age 緩存毫秒數

Cache-control 和 Expires

  1. 這兩個能夠一塊兒用,也能夠只用其中一個 【一塊兒用,優先級: Cache-Control > Expires
  2. Expires 是比較老的強緩存管理Header,由於它是絕對時間,而服務器時間和客戶端時間相差大,或者修改客戶端時間,就會影響緩存命中率
  3. Cache-control 是相對時間,受到的影響小一些

如何設置強緩存?

1. 代碼形式

經過代碼的形式,在web服務器的返回響應 header 中添加 Expies, Cache-control

java.util.Date date = new java.util.Date();    
response.setDateHeader("Expires",date.getTime()+20000); //Expires:過期期限值 
response.setHeader("Cache-Control", "public"); //Cache-Control來控制頁面的緩存與否,public:瀏覽器和緩存服務器均可以緩存頁面信息;
response.setHeader("Pragma", "Pragma"); //Pragma:設置頁面是否緩存,爲Pragma則緩存,no-cache則不緩存

設置不緩存

response.setHeader( "Pragma", "no-cache" );   
response.setDateHeader("Expires", 0);   
response.addHeader( "Cache-Control", "no-cache" );//瀏覽器和緩存服務器都不該該緩存頁面信息

2. web服務器配置

讓web服務器在響應資源的時候統一添加Expires和Cache-Control Header

nginx和apache做爲專業的web服務器,都有專門的配置文件,能夠配置expires和cache-control,這方面的知識,若是你對運維感興趣的話,能夠在百度上搜索「nginx 設置 expires cache-control」或「apache 設置 expires cache-control」都能找到很多相關的文章。

3. 強緩存的應用

  1. 強緩存是前端性能優化最有力的工具,沒有之一。

  2. 大量的靜態資源網站,必定要利用強緩存,提升響應速度

  3. 例子,京東頁面,強緩存到2026年。【這個強緩存能夠有】

  4. 使用強緩存後,如何更新網站呢?

    給文件加上 hash 值。

知乎上的完美解決方案
https://www.zhihu.com/question/20790576

  1. 注意點【強緩存針對靜態資源,動態資源不要,html資源不要。】

    強緩存還有一點須要注意的是,一般都是針對靜態資源使用,動態資源須要慎用,除了服務端頁面能夠看做動態資源外,那些引用靜態資源的html也能夠看做是動態資源,若是這種html也被緩存,當這些html更新以後,可能就沒有機制可以通知瀏覽器這些html有更新,尤爲是先後端分離的應用裏,頁面都是純html頁面,每一個訪問地址可能都是直接訪問html頁面,這些頁面一般不增強緩存,以保證瀏覽器訪問這些頁面時始終請求服務器最新的資源

3、協商緩存

1. 什麼是協商緩存?

如圖:返回http狀態304,Not Modified

說白了就是瀏覽器本身不肯定,沒有辦法決定,所以要找 服務器商量下。 服務器說能夠,那瀏覽器就直接從本身緩存裏面找出資源, 服務器說你這個不行啊,過時了。 我給你個新的,瀏覽器就拿新的咯。

協商緩存要發請求,全部header都是 response 和 request 一人一個。

2. 協商緩存如何控制?

協商緩存是利用的是【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】這兩對Header來管理的。

Response Header : Last-Modified, ETag
Request Header : If-Modified-Since , If-None-Match

3. 【Last-Modified,If-Modified-Since】緩存管理方式

  1. 第一次跟web服務器請求資源時,在 response 的 header 加上 Last-Modified【文件最後修改時間】

  2. 瀏覽器收到資源的時候,把資源文件和 Last-Modified 緩存起來

  3. 再次請求的時候, 在 Request Header 加上 If-Modified-Since 的 header, 這個值,就是 第一次web服務器返回的 Last-Modified。

  4. web服務器收到以後,判斷 Last-Modified-Since 和 Last-Modified 是否一致,一致則返回 304 Not Modified. 讓瀏覽器去加載緩存裏面的。

  5. 不一致的話,返回資源,並返回一個新的 Last-Modified

  6. 瀏覽器繼續緩存下來, 而後繼續上面的步驟。

【Last-Modified,If-Modified-Since】都是根據服務器時間返回的header,通常來講,在沒有調整服務器時間和篡改客戶端緩存的狀況下,這兩個header配合起來管理協商緩存是很是可靠的,可是有時候也會服務器上資源其實有變化,可是最後修改時間卻沒有變化的狀況,而這種問題又很不容易被定位出來,而當這種狀況出現的時候,就會影響協商緩存的可靠性。因此就有了另一對header來管理協商緩存,這對header就是【ETag、If-None-Match】。

4.【ETag、If-None-Match】的緩存管理的方式是

全部的步驟都是差很少的

  1. 發送請求,返回資源的時候,也返回了一個 ETag【文件的Hash值】

  2. 瀏覽器緩存資源,並緩存下 ETag

  3. 再次請求的時候,Request Header If-None-Match 把上次傳過來的 ETag 傳過去

  4. web服務器,在生成一個資源文件的 ETag, 而後跟傳過來的比較

  5. 同樣,返回 304 Not-Modified,瀏覽器從緩存拿

  6. 不同, web服務器返回資源,並返回一個新的 ETag, 而後重複上面操做。

強緩存 和 協商緩存的 緩存管理都是同樣的步驟哈。

5. 注意ETag的使用

  1. 在分佈式部署的時候,多臺機器的 Last-Modified 必須保持一致,不然協商緩存會出問題。

  2. 分佈式部署,不一樣的機器生成的 ETag 都會不同。 而後協商緩存就會出問題。【所以若是沒有搞定ETag 一致,就先關閉掉。】

  3. 協商緩存 須要 配合 強緩存使用 【不啓動強緩存,協商緩存也就不起做用】
    response header 包含了強緩存的管理 header

4、瀏覽器行爲對緩存的影響

若是資源已經被瀏覽器緩存下來,在緩存失效以前,再次請求時,默認會先檢查是否命中強緩存,若是強緩存命中則直接讀取緩存,若是強緩存沒有命中則發請求到服務器檢查是否命中協商緩存,若是協商緩存命中,則告訴瀏覽器仍是能夠從緩存讀取,不然才從服務器返回最新的資源。這是默認的處理方式,這個方式可能被瀏覽器的行爲改變:

  1. 當ctrl+f5強制刷新網頁時,直接從服務器加載,跳過強緩存和協商緩存;
  2. 當f5刷新網頁時,跳過強緩存,可是會檢查協商緩存;

5、注意點

勾選這個 disable cache 緩存, 則不會使用緩存

參考文章

  1. 《瀏覽器緩存知識小結及應用》
  2. 《HTTP緩存》
  3. 《瀏覽器 HTTP 協議緩存機制詳解》
相關文章
相關標籤/搜索