整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          一文搞懂瀏覽器緩存機制

          近在項目中遇到了 IE瀏覽器因緩存問題未能成功向后端發送 GET類型請求 的bug,然后順藤摸瓜順便看了看緩存的知識,覺得有必要總結跟大家分享一下。

          在前端開發中,性能一直都是被大家所重視的一點,然而判斷一個網站的性能最直觀的就是看網頁打開的速度。其中提高網頁反應速度的一個方式就是使用緩存。一個優秀的緩存策略可以縮短網頁請求資源的距離,減少延遲,并且由于緩存文件可以重復利用,還可以減少帶寬,降低網絡負荷。

          1. 介紹

          web緩存是指一個web資源(如html頁面,圖片,js,數據等)存在于web服務器和客戶端(瀏覽器)之間的副本。

          緩存會根據進來的請求保存輸出內容的副本;當下一個請求來到的時候,如果是相同的URL,緩存會根據緩存機制決定是直接使用副本響應訪問請求,還是向源服務器再次發送請求。比較常見的就是瀏覽器會緩存訪問過網站的網頁,當再次訪問這個URL地址的時候,如果網頁沒有更新,就不會再次下載網頁,而是直接使用本地緩存的網頁。只有當網站明確標識資源已經更新,瀏覽器才會再次下載網頁。至于瀏覽器和網站服務器是如何標識網站頁面是否更新的機制,將在后面介紹。

          1.1 web緩存的作用

          web緩存的作用顯而易見:

          1. 減少網絡帶寬消耗:無論對于網站運營者或者用戶,帶寬都代表著金錢,過多的帶寬消耗,只會便宜了網絡運營商。當Web緩存副本被使用時,只會產生極小的網絡流量,可以有效的降低運營成本。
          2. 降低服務器壓力:給網絡資源設定有效期之后,用戶可以重復使用本地的緩存,減少對源服務器的請求,間接降低服務器的壓力。同時,搜索引擎的爬蟲機器人也能根據過期機制降低爬取的頻率,也能有效降低服務器的壓力。
          3. 減少網絡延遲,加快頁面打開速度:帶寬對于個人網站運營者來說是十分重要,而對于大型的互聯網公司來說,可能有時因為錢多而真的不在乎。那Web緩存還有作用嗎?答案是肯定的,對于最終用戶,緩存的使用能夠明顯加快頁面打開速度,達到更好的體驗。

          1.2 web緩存的類型

          web緩存大致可以分為以下幾種類型 詳細內容:

          1. 數據庫數據緩存
          2. 服務器端緩存
          3. 瀏覽器端緩存
          4. web應用層緩存

          瀏覽器通過代理服務器向源服務器發起請求的原理如下圖:

          瀏覽器先向代理服務器發起web請求,再將請求轉發到源服務器。它屬于共享緩存,所以很多地方都可以使用其緩存資源,因此對于節省流量有很大作用。

          瀏覽器緩存是將文件保存在客戶端,在同一個會話過程中會檢查緩存的副本是否足夠新,在后退網頁時,訪問過的資源可以從瀏覽器緩存中拿出使用。通過減少服務器處理請求的數量,用戶將獲得更快的體驗

          下面著重關注一下瀏覽器緩存。

          2. web緩存的工作原理

          所有的緩存都是基于一套規則來幫助他們決定什么時候使用緩存中的副本提供服務(假設有副本可用的情況下,未被銷毀回收或者未被刪除修改)。這些規則有的在協議中有定義(如HTTP協議1.0和1.1),有的則是由緩存的管理員設置(如DBA、瀏覽器的用戶、代理服務器管理員或者應用開發者)。

          2.1 瀏覽器端的緩存規則

          對于瀏覽器端的緩存來講,這些規則是在HTTP協議頭和HTML頁面的 Meta標簽中定義的。他們分別從新鮮度校驗值兩個維度來規定瀏覽器是直接使用緩存中的副本,還是需要去源服務器獲取更新的版本。

          1. 新鮮度(過期機制):也就是緩存副本有效期。一個緩存副本必須滿足以下任一條件,瀏覽器會認為它是有效的,足夠新的,而直接從緩存中獲取副本并渲染:
          • 含有完整的過期時間控制頭信息(HTTP協議報頭),并且仍在有效期內
          • 瀏覽器已經使用過這個緩存副本,并且在一個會話中已經檢查過新鮮度
          1. 校驗值(驗證機制):服務器返回資源的時候有時在控制頭信息帶上這個資源的實體標簽Etag(Entity Tag),它可以用來作為瀏覽器再次請求過程的校驗標識。如過發現校驗標識不匹配,說明資源已經被修改或過期,瀏覽器需求重新獲取資源內容。

          2.2 瀏覽器緩存的控制

          2.2.1 使用HTML的 Meta 標簽

          <
          META HTTP
          -
          EQUIV
          =
          "Pragma"
           CONTENT
          =
          "no-cache"
          >
          

          上述代碼的作用是告訴瀏覽器當前頁面不被緩存,每次訪問都需要去服務器拉取。使用上很簡單,但只有部分瀏覽器可以支持,而且所有緩存代理服務器都不支持,因為代理不解析HTML內容本身。可以通過這個頁面測試你的瀏覽器是否支持:[Pragma No-Cache Test] (http://www.procata.com/cachetest/tests/pragma/index.php)。

          2.2.2 使用緩存有關的HTTP消息報頭

          一個URI的完整HTTP協議交互過程是由HTTP請求和HTTP響應組成的。有關HTTP詳細內容可參考《Hypertext Transfer Protocol — HTTP/1.1》、《HTTP協議詳解》等。

          在HTTP請求和響應的消息報頭中,常見的與緩存有關的消息報頭有:

          稍微解釋一下:

          1. Cache-Control

          1. max-age(單位為s)指定設置緩存最大的有效時間,定義的是時間長短。當瀏覽器向服務器發送請求后,在max-age這段時間里瀏覽器就不會再向服務器發送請求了。我們來找個資源看下。比如QQ推廣上的css資源,max-age=3600,也就是說緩存有效期為3600秒(也就是1h)。于是在1天內都會使用這個版本的資源,即使服務器上的資源發生了變化,瀏覽器也不會得到通知。max-age會覆蓋掉Expires,后面會有討論


          1. s-maxage(單位為s)同max-age,只用于共享緩存(比如CDN緩存)。比如,當s-maxage=60時,在這60秒中,即使更新了CDN的內容,瀏覽器也不會進行請求。也就是說max-age用于普通緩存,而s-maxage用于代理緩存。如果存在s-maxage,則會覆蓋掉max-age和Expires header。
          2. public 指定響應會被緩存,并且在多用戶間共享。也就是下圖的意思。如果沒有指定public還是private,則默認為public。


          1. private 響應只作為私有的緩存(見下圖),不能在用戶間共享。如果要求HTTP認證,響應會自動設置為 private


          1. no-cache 指定不緩存響應,表明資源不進行緩存,但是設置了 no-cache 之后并不代表瀏覽器不緩存,而是在獲取緩存前要向服務器確認資源是否被更改。因此有的時候只設置 no-cache 防止緩存還是不夠保險,還可以加上 private 指令,將過期時間設為過去的時間。
          2. no-store 絕對禁止緩存,一看就知道如果用了這個命令當然就是不會進行緩存啦~每次請求資源都要從服務器重新獲取。
          3. must-revalidate 指定如果頁面是過期的,則去服務器進行獲取。這個指令并不常用,就不做過多的討論了。

          cache-control的種類這么多,然而怎么使用它們呢,參看下圖:

          2. Expires

          緩存過期時間,用來指定資源到期的時間,是服務器端的具體的時間點。也就是說,Expires=max-age + 請求時間 ,需要和Last-modified結合使用。但在上面我們提到過,cache-control的優先級更高。Expires是Web服務器響應消息頭字段,在響應http請求時告訴瀏覽器在過期時間前瀏覽器可以直接從瀏覽器緩存取數據,而無需再次請求。

          3. Last-modified & If-modified-since

          服務器端文件的最后修改時間,需要和cache-control共同使用,是檢查服務器端資源是否更新的一種方式。當瀏覽器再次進行請求時,會向服務器傳送If-Modified-Since報頭,詢問Last-Modified時間點之后資源是否被修改過。如果沒有修改,則返回碼為304,使用緩存;如果修改過,則再次去服務器請求資源,返回碼和首次請求相同為200,資源為服務器最新資源。

          4. Etag & & If-None-Match

          根據實體內容生成一段hash字符串,標識資源的狀態,由服務端產生。瀏覽器會將這串字符串傳回服務器,驗證資源是否已經修改,如果沒有修改,過程如下:

          2.2.3 緩存報頭種類與優先級

          1. Cache-Control與Expires

          Cache-Control與 Expires的作用一致,都是指明當前資源的有效期,控制瀏覽器是否直接從瀏覽器緩存取數據還是重新發請求到服務器取數據。只不過 Cache-Control的選擇更多,設置更細致,如果同時設置的話,其優先級高于 Expires。

          2. Last-Modified與ETag

          你可能會覺得使用 Last-Modified 已經足以讓瀏覽器知道本地的緩存副本是否足夠新,為什么還需要 Etag(實體標識)呢?HTTP1.1中Etag的出現主要是為了解決幾個 Last-Modified 比較難解決的問題:

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

          Etag是服務器自動生成或者由開發者生成的對應資源在服務器端的唯一標識符,能夠更加準確的控制緩存。Last-Modified與ETag是可以一起使用的,服務器會優先驗證ETag,一致的情況下,才會繼續比對Last-Modified,最后才決定是否返回304。Etag的服務器生成規則和強弱Etag的相關內容可以參考,《互動百科-Etag》和《HTTP Header definition》,這里不再深入。

          3. Last-Modified/ETag 與 Cache-Control/Expires

          配置 Last-Modified/ETag的情況下,瀏覽器再次訪問統一URI的資源,還是會發送請求到服務器詢問文件是否已經修改,如果沒有,服務器會只發送一個304回給瀏覽器,告訴瀏覽器直接從自己本地的緩存取數據;如果修改過那就整個數據重新發給瀏覽器;

          Cache-Control/Expires則不同,如果檢測到本地的緩存還是有效的時間范圍內,瀏覽器直接使用本地副本,不會發送任何請求。兩者一起使用時, Cache-Control/Expires的優先級要高,即當本地副本根據 Cache-Control/Expires發現還在有效期內時,則不會再次發送請求去服務器詢問修改時間 Last-Modified或實體標識 Etag了。

          一般情況下,兩者會配合一起使用,因為即使服務器設置緩存時間, 當用戶點擊“刷新”按鈕時,瀏覽器會忽略緩存繼續向服務器發送請求,這時 Last-Modified/ETag將能夠很好利用304,從而減少響應開銷。

          2.2.4 哪些請求不能被緩存?

          無法被瀏覽器緩存的請求:

          • HTTP信息頭中包含Cache-Control:no-cache,pragma:no-cache,或Cache-Control:max-age=0等告訴瀏覽器不用緩存的請求
          • 需要根據Cookie,認證信息等決定輸入內容的動態請求是不能被緩存的
          • 經過HTTPS安全加密的請求(有人也經過測試發現,ie其實在頭部加入Cache-Control:max-age信息,firefox在頭部加入Cache-Control:Public之后,能夠對HTTPS的資源進行緩存,參考《HTTPS的七個誤解》)
          • POST請求無法被緩存
          • HTTP響應頭中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的請求無法被緩存

          3. 使用緩存流程

          一個用戶發起一個靜態資源請求的時候,瀏覽器會通過以下幾步來獲取并展示資源:

          緩存行為主要由緩存策略決定,而緩存策略由內容擁有者設置。這些策略主要通過特定的HTTP頭部來清晰地表達。

          以上過程也可以被概括為三個階段:

          1. 本地緩存階段:先在本地查找該資源,如果有發現該資源,而且該資源還沒有過期,就使用這一個資源,完全不會發送http請求到服務器;
          2. 協商緩存階段:如果在本地緩存找到對應的資源,但是不知道該資源是否過期或者已經過期,則發一個http請求到服務器,然后服務器判斷這個請求,如果請求的資源在服務器上沒有改動過,則返回304,讓瀏覽器使用本地找到的那個資源;
          3. 緩存失敗階段:當服務器發現請求的資源已經修改過,或者這是一個新的請求(在本來沒有找到資源),服務器則返回該資源的數據,并且返回200, 當然這個是指找到資源的情況下,如果服務器上沒有這個資源,則返回404。

          4. 用戶操作行為與緩存的關系

          用戶在使用瀏覽器的時候,會有各種操作,比如輸入地址后回車,按F5刷新等,這些行為會對緩存有什么影響呢?

          通過上表我們可以看到,當用戶在按 F5進行刷新的時候,會忽略Expires/Cache-Control的設置,會再次發送請求去服務器請求,而Last-Modified/Etag還是有效的,服務器會根據情況判斷返回304還是200;

          而當用戶使用 Ctrl+F5進行強制刷新的時候,只是所有的緩存機制都將失效,重新從服務器拉去資源。

          • 普通刷新 – 當按下F5或者點擊刷新按鈕來刷新頁面的時候,瀏覽器將繞過本地緩存來發送請求到服務器, 此時, 協商緩存是有效的
          • 強制刷新 – 當按下ctrl+F5來刷新頁面的時候, 瀏覽器將繞過各種緩存(本地緩存和協商緩存), 直接讓服務器返回最新的資源
          • 回車或轉向 – 當在地址欄上輸入回車或者按下跳轉按鈕的時候, 所有緩存都生效

          5. 如何從緩存角度改善站點

          • 同一個資源保證URL的穩定性
          • 給css、js、圖片等資源增加HTTP緩存頭,并強制入口html不被緩存
          • 減少對Cookie的依賴
          • 多用Get方式請求動態Cgi
          • 動態CGI也是可以被緩存

          關注微信公眾號:安徽思恒信息科技有限公司,了解更多技術內容……

          近一次移動端Vue應用的上線,導致某些用戶使用某些功能時出現問題,經主動清空緩存后恢復。有時候清空微信應用的存儲空間緩存仍不能解決問題,此時安卓機可借助微信TBS調試工具 http://debugx5.qq.com (微信中打開頁面,勾選最下面四個選項清除緩存),但該工具目前只支持安卓手機,蘋果機就比較麻煩了。為了找到問題的本質,從根本上避免問題,最近瀏覽了一些文章,其中有一篇對瀏覽器緩存的分析及在Nginx中對應的處理策略總結的比較好,這里分享給大家。

          • 原文標題:http常用緩存策略及vue-cli單頁面應用服務器端(nginx)如何設置緩存
          • 原文地址:http://www.shanhuxueyuan.com/news/detail/125.html

          以下為原文。

          關于http或者是瀏覽器緩存策略,我認為可以分為這三種:

          • 不使用緩存
          • 強制使用緩存
          • 協商使用緩存

          不使用緩存

          有時,我們希望瀏覽器永遠都不要使用緩存,全部到服務器拉取數據,此時即為不使用緩存,我們可以在服務端通過Cache-Control為 no-store實現。

          服務器端針對上面文件設置了no-store,可以看到在請求的時候,無論怎么刷新,都是返回200,不會顯示304,也不會顯示“memory cache”或“disk cache”,說明真的都是從服務器重新拉取數據。

          比如我們想設置html文件不緩存,可以在域名的解析配置中如下設置,當文件后綴為html或htm時add_header Cache-Control "no-store"

          server {
          listen 80;
          server_name yourdomain.com;
          location / {
              try_files $uri $uri/ /index.html;
              root /yourdir/;
              index index.html index.htm;
          
              if ($request_filename ~* .*\.(?:htm|html)$)
              {
                  add_header Cache-Control "no-store";  //對html文件設置永遠不緩存
              }  
            }
          }
          

          這種方式缺點就是每次都要去服務端拉取文件,即使文件沒有更新,很明顯這樣增加了不必要的帶寬消耗。

          如果文件沒有更新,我們就使用緩存,只有更新了才去拉取最新文件,這樣多好,這就是協商緩存。

          協商緩存

          協商緩存就是瀏覽器攜帶文件緩存標識(如Last-Modified或ETag),向服務器發送請求,由服務器根據文件緩存標識來決定是否使用緩存,如果文件沒有更新,則告訴瀏覽器使用本地緩存,如果文件更新了,則直接返回新文件內容。

          可以看出,相比不使用緩存,協商緩存是會大大減少帶寬消耗的。

          • 協商緩存生效,返回304 和 Not Modified

          • 協商緩存無效,返回200和請求文件

          我們在瀏覽器調試頁面,可以看到有304的,即是使用了協商緩存

          服務器返回的header中會有Last-Modified和ETag標識,而瀏覽器請求header中會包含If-Modified-Since和If-None-Match

          Last-Modified和If-Modified-Since

          在 http 1.0 版本中,第一次請求資源時服務器通過 Last-Modified 來設置響應頭的緩存標識,并且把資源最后修改的時間作為值填入,然后將資源返回給瀏覽器。在第二次請求時,瀏覽器會首先帶上 If-Modified-Since 請求頭去訪問服務器,服務器會將 If-Modified-Since 中攜帶的時間與資源修改的時間匹配,如果時間不一致,服務器會返回新的資源,并且將 Last-Modified 值更新,作為響應頭返回給瀏覽器。如果時間一致,表示資源沒有更新,服務器返回 304 狀態碼,瀏覽器拿到響應狀態碼后從本地緩存數據庫中讀取緩存資源。

          這種方式有2個弊端,第一個就是當服務器中的資源增加了一個字符,后來又把這個字符刪掉,本身資源文件并沒有發生變化,但修改時間發生了變化。當下次請求過來時,服務器也會把這個本來沒有變化的資源重新返回給瀏覽器;第二個就是修改時間的單位為秒,所以存在1s的間隙,即使更新了,也會認為沒有更新。

          ETag和If-None-Match

          在 http 1.1 版本中,服務器通過 Etag 來設置響應頭緩存標識。Etag 的值由服務端生成,可以認為是文件內容的hash值。在第一次請求時,服務器會將資源和 Etag 一并返回給瀏覽器,瀏覽器將兩者緩存到本地緩存數據庫。在第二次請求時,瀏覽器會將 Etag 信息放到 If-None-Match 請求頭去訪問服務器,服務器收到請求后,會將服務器中的文件標識與瀏覽器發來的標識進行對比,如果不相同,服務器返回更新的資源和新的 Etag ,如果相同,服務器返回 304 狀態碼,瀏覽器讀取緩存。

          兩者對比

          • 首先在精確度上,Etag要優于Last-Modified。Last-Modified的時間單位是秒,如果某個文件在1秒內改變了多次,那么他們的Last-Modified其實并沒有體現出來修改,但是Etag每次都會改變確保了精度;如果是負載均衡的服務器,各個服務器生成的Last-Modified也有可能不一致。
          • 第二在性能上,Etag要遜于Last-Modified,畢竟Last-Modified只需要記錄時間,而Etag需要服務器通過算法來計算出一個hash值。
          • 第三在優先級上,服務器校驗優先考慮Etag

          協商緩存服務端配置

          可以在服務端通過設置Cache-Control為 no-cache或者max-age=0來實現

          強制緩存

          有時我們希望文件強制使用緩存,比如通過vue-cli產生的js和css,文件名上帶有hash值,所以如果文件名沒有變的時候,我們希望文件永久緩存,這樣可以減少網絡請求。

          強制緩存整體流程比較簡單,就是在第一次訪問服務器取到數據之后,在過期時間之內不會再去重復請求。實現這個流程的核心就是如何知道當前時間是否超過了過期時間。

          強制緩存的過期時間通過第一次訪問服務器時返回的響應頭獲取。在 http 1.0 和 http 1.1 版本中通過不同的響應頭字段實現。

          在 http 1.0 版本中,強制緩存通過 Expires 響應頭來實現。 expires 表示未來資源會過期的時間。也就是說,當發起請求的時間超過了 expires 設定的時間,即表示資源緩存時間到期,會發送請求到服務器重新獲取資源。而如果發起請求的時間在 expires 限定的時間之內,瀏覽器會直接讀取本地緩存數據庫中的信息(from memory or from disk),兩種方式根據瀏覽器的策略隨機獲取。

          在 http 1.1 版本中,可以設置Cache-Control中的 max-age=xxx ,來表示緩存的資源將在 xxx 秒后過期。一般來說,為了兼容,兩個版本的強制緩存都會被實現。

          為什么有了Expires,后來又增加了max-age呢,這是因為Expires是一個絕對時間,有可能客戶端的時間和服務器不一致,導致緩存不能按照預期進行,而max-age則是個相對時間,比如3600s,自瀏覽器請求后3600s之內,都使用本地緩存,和客戶端的時間沒關系。

          vue-cli緩存策略

          由于打包后的js、css和圖片,一般名稱都帶有hash值,名稱中的hash變了,自然會拉取新文件,所以我們可以將這類文件設置為強制緩存,只要文件名不變,就一直緩存,比如緩存100天或者一年。

          而html文件則不能設為強制緩存,一般html名稱是沒法帶hash值的,所以html如果設置了強制緩存,則永遠也沒法更新,html不更新,其引用的js、css等名稱也不會更新,則整個服務都沒有更新,只能讓用戶清除緩存了。所以針對html文件,我們可以設置協商緩存或者直接不使用緩存,本身html文件都比較小,我是直接使用了不緩存,nginx配置如下。

          server {
          listen 80;
          server_name yourdomain.com;
          location / {
              try_files $uri $uri/ /index.html;
              root /yourdir/;
              index index.html index.htm;
          
              if ($request_filename ~* .*\.(js|css|woff|png|jpg|jpeg)$)
              {
                  expires    100d;  //js、css、圖片緩存100天
                  #add_header Cache-Control "max-age = 8640000"; //或者設置max-age
              }
          
              if ($request_filename ~* .*\.(?:htm|html)$)
              {
                  add_header Cache-Control "no-store";  //html不緩存
              }
            }
          }

          歡迎微信搜索關注公眾號:半路雨歌,查看更多技術干貨文章

          緩存,這個問題在面試中出現的頻率還是很高的,也是我們日常工作中必知必會的。

          所以在本文中,我們來嘗試對HTTP 協議中規定的很多請求頭響應頭來做總結和歸納,讓大家了解到瀏覽器是如何通過他們來控制緩存的

          經典 GET 請求過程

          下圖是一個經典的 GET 請求的處理過程:

          當一個請求達到時,瀏覽器會先檢查被訪問的資源是否已被緩存。

          如果未被緩存(緩存未命中 cache miss),則將請求轉發給原始服務器

          如果已被緩存(緩存命中,cache hit),則會檢查緩存是否足夠新鮮

          如果緩存的副本足夠新鮮,則直接將副本返回客戶端,否則會向服務端發起新鮮度驗證(revalidation)。如果發現與服務端文件一致,則將本地緩存副本返回給客戶端,否則將請求轉發給原始服務器。

          在這個過程中,由緩存提供的服務在所有請求占比中的比例稱為緩存命中率(cache hit rat)。

          這種描述方式只能描述請求級別的命中情況,無法體現具體有多少流量來自緩存。

          比如一個訪問頻次很低尺寸很大的文件,如果以該命中率來描述的話,命中率非常低。但是這個文件卻占據了絕大多數的訪問流量。

          因此還需要另一個命中率指標來描述,那就是字節命中率(byte hit rate)。字節命中率表示的是緩存提供的字節在所有傳輸字節中的占比。

          緩存機制

          瀏覽器常用校驗緩存的機制有兩種:

          • 文檔過期(document expiration)
          • 服務端再驗證(server revalidation)

          下面我們來分別介紹下這兩種機制。

          文檔過期

          HTTP 通過 Cache-Control:max-ageExpires 這兩個響應頭信息, 讓原始服務器向每個文檔附加一個“過期日期”。在緩存文檔過期之前,緩存可以以任意頻次使用這些副本,而無需與服務端聯系。
          Expires 首部與 Cache-Control:max-age 首部本質上是一樣的,區別是 Expires 是
          HTTP/1.0 協議規定的首部,且首部取值為一個絕對時間,在這個時間之后緩存失效;Cache-Control:max-age 是 HTTP/1.1 協議規定的首部,且首部取值是一個相對時間,單位為

          一個絕對,一個相對。

          服務端再驗證

          HTTP 定義了 5 個條件請求首部來完成服務器再驗證:

          1. If-Modified-Since
          2. If-None-Match
          3. If-Unmodified-Since
          4. If-Range
          5. If-Match

          其中最有用的是 If-Modified-Since If-None-Match 兩個首部。

          一、If-Modified-Since: Date 再驗證

          If-Modified-Since: Date 再驗證請求流程分兩種:

          1、自指定日期后,文檔被修改了,If-Modified-Since 條件為,GET 請求就會執行。攜帶新首部的新文檔會被返回給緩存,新首部除了其他信息以外,還包含了一個新的過期日期。

          2、自指定日期后,文檔沒有被修改過,If-Modified-Since 條件為,則會向客戶端返回一個304 Not Modified 響應報文,為了提高有效性,一般會發送一個新的過期日期,不會返回文檔的主體。

          If-Modified-Since 請求首部通常與 Last-Modified 服務器響應首部配合工作。原始服務器會將最后的修改日期附加到文檔上去。當瀏覽器要對已緩存的文檔進行再驗證時,就會包含一個 If-Modified-Since首部,其中攜帶有最后修改已緩存副本的日期:

          If-Modified-Since: <cached last-modified date>

          這里以W3C網站為例:




          從上面兩張圖上,可以分別看到請求頭信息中的 If-Modified-Since 和響應頭信息中的 Last-Modified。

          說白了,就是本地記錄的修改日期,與服務器那邊記錄的修改日期做對比。如果服務的比較新,就重新過去,否則加載本地的。

          上圖我第一次進來,因為本地并沒有If-Modified-Since 記錄,所以只能看到響應頭中有最后修改時間信息,以及返回的200狀態碼。

          當我再次刷新網頁之后:



          瞧,請求頭也有信息了。因為If-Modified-Since 和 Last-Modified兩個值是一樣的,所以服務器校驗本頁面為緩存,返回304狀態碼。


          If-None-Match: etag 實體標簽驗證

          在某些情況下,If-Modified-Since: Date 可能無法很好地解決緩存問題。

          比如一個被周期性復寫的文件,雖然修改日期每次都有變化,但是文件的內容往往是一樣的,如果此時還根據最后修改時間去判定是否為緩存,顯示是不合適的。

          這種情況下,就需要借助實體標簽(Etag)驗證了。

          實體標簽就是“版本標識符”,是附加到文檔上的任意標簽(引用字符串),可能包含了文檔的序列號或版本名,或者是文檔內容的校驗信息。
          If-None-Match: etag 實體標簽驗證的工作過程與 If-Modified-Since: Date 再驗證的工作過程基本一致,不同的是,服務器會在響應中附加一個 Etag 響應頭。當緩存要對已緩存的文檔進行再驗證時,就會將這個 etag 放到 If-None-Match 請求頭中去。

          還是以上面的請求為例:



          可以看到,If-none-match 在chrome網絡面板中的位置,就是在 If-modifed-since 后面,只是它對應的不是修改日期,而是上面相應的etag罷了。

          說簡單點,就是hash字符串校驗。

          注意:如果你是第一次訪問該頁面,請求頭中同樣沒有 if-none-match 信息。

          其他相關屬性

          一、服務器端響應

          服務端通過Cache-Control 來對響應緩存做限制,以下控制優先級按順序依次遞減:

          Cache-Control: no-store 禁止緩存對響應進行復制。
          Cache-Control: no-cache/ Pragma: no-cache 緩存可以復制響應,但是在與原始服務器進行新鮮度再驗證之前不能將其提供給客戶端。Pramga: no-cache 為了兼容 HTTP/1.0,優先級低于 Cache-Control: no-cache。
          Cache-Control: must-revalidate 在事前沒有跟原始服務器進行再驗證的情況下,緩存不能提供緩存副本。
          Cache-Control: max-age max-age 指定的秒數內有效。max-age 為零時,不可緩存。
          Expires: Date 在實際的絕對日期之前有效。

          二、客戶端請求
          客戶端同樣可以通過 Cache-Control 請求首部來強化或放松對過期時間的限制。以下是使用時的具體參數及說明:

          Cache-Control: max-stale=< s > 緩存可以隨意提供副本,如果指定的秒數,那么在這段時間內,文檔不能過期。
          Cache-Control: min-fresh=< s > 至少在未來< s >秒內文檔保持新鮮。
          Cache-Control: max-age=< s > 緩存無法返回緩存時間超過< s >的文檔。如果與 max-stale 通用,max-stale 優先級更高。
          Cache-Control: no-cache/Pragma: no-cache 除非進行了再驗證,否則客戶端不接受已緩存的資源。
          Cache-Control: no-store 緩存應該刪除本地緩存副本,使用原始服務器響應。
          Cache-Control: only-if-cache 只有當緩存中有副本存在時,客戶端才會獲取一份副本。

          總結

          好了,緩存就暫時先說到這里。最后讓我們再來看下瀏覽器的緩存執行流程,鞏固一下吧。

          瀏覽器首次請求:


          瀏覽器再次請求時:


          主站蜘蛛池模板: 亚洲国产一区二区三区青草影视| 久久精品国内一区二区三区| 亚洲欧美成人一区二区三区 | 亚洲日韩国产欧美一区二区三区| 国产伦精品一区二区三区视频猫咪| 福利片福利一区二区三区| 国产成人高清亚洲一区91| 国产主播一区二区三区在线观看| 亚洲国产综合无码一区二区二三区| 国内精品无码一区二区三区| 亚洲色无码专区一区| 国产一区二区三区在线观看精品| 亚洲综合在线成人一区| 亚洲一区二区三区免费在线观看| 久久人做人爽一区二区三区| 国产伦精品一区二区三区视频猫咪| 亚洲AV日韩AV天堂一区二区三区 | 久久精品国产免费一区| 天堂一区人妻无码| 91福利国产在线观一区二区| 国产精品一区二区久久国产| 一区二区免费国产在线观看| 精品国产AV一区二区三区| 一夲道无码人妻精品一区二区| 理论亚洲区美一区二区三区 | 亚洲毛片不卡av在线播放一区| 日韩精品中文字幕无码一区 | 久久se精品一区精品二区| 精品理论片一区二区三区| 国产精品一区二区无线| 国产伦精品一区二区三区无广告| 国产SUV精品一区二区四 | 亚洲av无码一区二区乱子伦as| 久久精品国产第一区二区| 久久se精品动漫一区二区三区| 看电影来5566一区.二区| 国产对白精品刺激一区二区| 99精品国产一区二区三区2021| 在线免费观看一区二区三区| 国产精品熟女视频一区二区| 无码AV一区二区三区无码|