瀏覽器緩存機制分析

瀏覽器緩存

基礎概念

緩存無處不在,有客戶端緩存,服務端緩存,代理服務器緩存等等。和前端相關的緩存通常都是指http緩存,也就是瀏覽器緩存。javascript

就是說ajax請求以後,會把請求的url和返回的響應結果保存在緩存中,當下一次調用ajax發送相同的請求時,瀏覽器會從緩存中把數據取出來,這是爲了提升頁面的響應速度和用戶體驗,何時會出現這個現象呢,就是要這兩次的請求url和請求參數徹底同樣的時候,瀏覽器就不會與服務器交互。css

緩存的優缺點

優勢

如今說一下緩存的好處,好處顯而易見嘛,就是說請求一些靜態資源,js,css,圖片這些,不會變化的資源,請求會變得更快,加快了客戶端加載網頁的速度,提升了頁面的響應速度,也減小了冗餘數據的傳遞,節省了網絡帶寬流量,減小服務端的負擔,大大提升了網站性能。html

缺點

可是缺點也顯而易見,客戶端和服務端交互的時候,服務端的數據雖然變了,可是頁面緩存沒有改變,對於相同的url,ajax提交過去之後,瀏覽器是從緩存中拿數據,這種狀況確定是不被容許的。前端

那麼何時會觸發緩存呢,在這以前先說一下緩存機制吧。java

緩存機制

緩存通常分爲強制緩存協商緩存,接下來將分別介紹一下這兩個緩存機制。ajax

強制緩存

就是緩存中已經有了請求數據的時候,客戶端直接從緩存中獲取數據,只有當緩存中沒有請求數據的時候,客戶端纔會從服務端拿取數據。算法

協商緩存

也成爲對比緩存,就是說客戶端會從緩存中獲取到一個緩存數據的標識,根據這個標識會請求服務端驗證是否失效,若是沒有失效,服務端會返回304,這時候客戶端就直接從緩存中取數據,若是失效了,服務端會返回新的數據。瀏覽器

這兩種緩存機制能夠同時存在,不過強制緩存的優先級高於協商緩存。緩存

如今咱們簡單的瞭解了一下緩存機制的原理,該說一下何時會觸發緩存,服務端是如何判斷緩存是否失效呢?你們都知道,發送請求的時候會有請求數據和響應數據,這個被稱爲報文,報文中包含首部header和主體部分body。與緩存相關的規則信息就包含在header中。body中的內容就是http請求真正要傳輸的數據。舉個http報文的頭部例子服務器

1114764-20171218110148521-735904414.png

如今咱們對報文中出現的與緩存有關的信息分析一下

強制緩存

服務器響應的header中會用兩個字段來代表,Expires和Cache-Control。

Expires

Expires的值是服務端返回的數據到期時間。當再次請求時的請求時間小於返回的此時間,則直接使用緩存數據,可是由於客戶端和服務端的時間可能有偏差,因此這個緩存命中可能會有偏差,另外一方面,expires是http1.0的產物,因此如今大多數都使用Cache-Control

Cache-Control

Cache-Control有不少產物,不一樣的屬性表明的意義不一樣。

private: 客戶端能夠緩存

public: 客戶端和服務器能夠緩存

max-age=t:緩存內容在t秒後失效

no-cache:須要使用協商緩存來驗證緩存數據

no-store:全部內容不使用緩存

協商緩存

協商緩存須要判斷是否能夠用緩存,瀏覽器第一次請求數據的時候,服務器會將緩存標識與數據一塊兒響應給客戶端,客戶端將他們備份到緩存中,再次請求時,客戶端會將緩存中的標識發送給服務器,服務器根據此標識判斷是否失效,若是沒有失效,服務端返回304狀態碼,瀏覽器拿到此狀態嗎就能夠直接使用緩存數據了。對於協商緩存來講,緩存標識很重要,對於理解協商緩存,這是重點。

接下來介紹一下協商緩存的緩存方案

Last-Modified

Last-Modified

服務端在響應請求時,會返回資源的最後修改時間

If-Modified-Since

客戶端再次請求服務端的時候,請求頭會包含這個字段,後面跟着在緩存中獲取的資源的最後修改時間。服務端收到請求發現此請求頭中有If-Modified-Since字段,會與被請求資源的最後修改時間進行對比,若是一致則會返回304和響應報文頭,瀏覽器從緩存中獲取數據便可。從字面上看,就是說從某個時間節點開始看,是否被修改了,若是被修改了,就返回整個數據和200 OK,若是沒有被修改,服務端只要返回響應頭報文,304 Not Modified.

If-Unmodified-Since

和If-Modified-Since相反,就是說從某個時間點開始看,是否沒有被修改.若是沒有被修改,就返回整個數據和200 OK,若是被修改了,不傳輸和返回412 Precondition failed (預處理錯誤)

If-Modified-Since和If-Unmodified-Since區別就是一個是修改了返回數據一個是沒修改返回數據。

Last-Modified也有缺點,就是說服務端的資源只是改了下修改時間,可是其實裏面的內容並無改變,會由於Last-Modified發生了改變而返回整個數據,爲了解決這個問題,http1.1推出了Etag

Etag

Etag

服務端響應請求時,經過此字段告訴客戶端當前資源在服務端生成的惟一標識(生成規則由服務端決定)

If-None-Match

再次請求服務端的時候,客戶端的請求報文頭部會包含此字段,後面的值是從緩存中獲取的標識,服務端接收到報文後發現If-None-Match則與被請求的資源的惟一標識對比。若是相同,說明資源不用修改,則響應header,客戶端直接從緩存中獲取數據,返回狀態碼304,若是不一樣,說明資源被改過,返回整個數據,200 OK。

可是實際應用中因爲Etag的計算是使用算法計算出來的,而算法會佔用服務端的資源,全部服務端的資源都是寶貴的,因此不多使用Etag。

如今順便說一下不一樣的刷新的請求執行過程哈

  1. 瀏覽器直接輸入url,回車
    瀏覽器發現緩存中有這個文件了,不用繼續請求了,直接去緩存中拿(最快)
  2. F5
    告訴瀏覽器,去服務端看下文件是否過時了,因而瀏覽器發了一個請求帶上If-Modified-Since
  3. Ctrl+F5
    告訴瀏覽器,先把緩存刪了,再去服務端請求完整的資源文件過來,因而瀏覽器就完成了強制更新的操做

若是不想使用緩存怎麼辦呢,接下來講一下解決方法

解決方法

  1. 在ajax發送請求前加上 xmlHttpRequest.setRequestHeader(「Cache-Control」,」no-cache」);
  2. 在服務端加 header(「Cache-Control: no-cache, must-revalidate」);
  3. 在ajax發送請求前加上 xmlHttpRequest.setRequestHeader(「If-Modified-Since」,」0″);
  4. 在 Ajax 的 URL 參數後加上 "?fresh=" + Math.random(); //固然這裏參數 fresh 能夠任意取了
  5. 第五種方法和第四種相似,在 URL 參數後加上 "?timestamp=" + new Date().getTime();
  6. 用POST替代GET:不推薦
  7. jQuery提供一個防止ajax使用緩存的方法:
<script type="text/javascript" language="javascript">
     $.ajaxSetup ({ 
           cache: false //close AJAX cache 
      }); 
</script>
  1. 修改load 加載的url地址,如在url 多加個時間參數就能夠:
function loadEventInfoPage(eventId){

    $.ajaxSetup ({ 
       cache: true // AJAX cache  下面加上時間後load的頁面中的js、css圖片等都會從新加載,   

         //加上這句action會從新加載,可是js、css、圖片等會走緩存 
    }); 
    $("#showEventInfo").load(ctx + "/custEvents/viewEvent.action",  {"complaint.Id":eventId, "tt":(new Date()).getTime()},function(){}) 
}

9.設置html的緩存

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">    
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">    
<META HTTP-EQUIV="Expires" CONTENT="0">
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息