由於公司沒外網,好久沒寫技術博客了,幾天無聊寫一下瀏覽器緩存機制,以及如何禁止緩存。
個人理解:
瀏覽器第一次訪問一個地址時會緩存靜態文件(html,css,js),然后當第二次訪問時會查看緩存是否過期,如果沒有過期不會重新下載網頁,直接使用緩存中的網頁。只有網站明確標明已經更新了,瀏覽器才會重新下載網頁。
HTTP緩存機制:
當瀏覽器向服務端發送請求或者下載靜態文件時會根據Response Header里面的Cache-Control和expires兩個屬性來判斷是否讀取緩存中的數據,其中Cache-Control的優先級高。
Cache-Control對應的值:
Public:指示響應可被任何緩存區緩存。
Private:指示對於單個用戶的整個或部分響應消息,不能被共享緩存處理。這允許服務器僅僅描述當用戶的部分響應消息,此響應消息對於其他用戶的請求無效。
no-cache:指示請求或響應消息不能緩存
no-store:用於防止重要的信息被無意的發布。在請求消息中發送將使得請求和響應消息都不使用緩存。
max-age:指示瀏覽器可以接收生存期不大於指定時間(以秒為單位)的響應。
min-fresh:指示瀏覽器可以接收響應時間小於當前時間加上指定時間的響應。
具體步驟:
①瀏覽器第一次訪問服務器資源 /index.html
在瀏覽器中沒有緩存文件,直接向服務器發送請求。
服務器返回 200 OK,實體中返回 index.html文件內容,並設置一個緩存過期時間,一個文件修改時間,一個根據index.html內容計算出來的實體標記Entity Tag,簡稱Etag。
瀏覽器將/index.html路徑的請求緩存到本地。
②瀏覽器第二次訪問服務器資源 /index.html
由於本地已經有了此路徑下的緩存文件,所以這一次就不直接向服務器發送請求了。
首先,進行緩存過期判斷。瀏覽器根據①中設置緩存過期時間判斷緩存文件是否過期。
情景一:若沒有過期,則不向服務器發送請求,直接使用緩存中的結果,此時我們在瀏覽器控制台中可以看到 200 OK(from cache) ,此時的情況就是完全使用緩存,瀏覽器和服務器沒有任何交互的。
情景二:若已過期,則向服務器發送請求,此時請求中會帶上①中設置的文件修改時間,和Etag
然后,進行資源更新判斷。服務器根據瀏覽器傳過來的文件修改時間,判斷自瀏覽器上一次請求之后,文件是不是沒有被修改過;根據Etag,判斷文件內容自上一次請求之后,有沒有發生變化
情形一:若兩種判斷的結論都是文件沒有被修改過,則服務器就不給瀏覽器發index.html的內容了,直接告訴它,文件沒有被修改過,你用你那邊的緩存吧—— 304 Not Modified,此時瀏覽器就會從本地緩存中獲取index.html的內容。此時的情況叫協議緩存,瀏覽器和服務器之間有一次請求交互。
情形二:若修改時間和文件內容判斷有任意一個沒有通過,則服務器會受理此次請求,之后的操作同①
服務端:
服務端通過If-Modified-Since(Last-Modified)和If-None-Match(Etag)這兩個屬性的值來判斷緩存是否失效的。
Last-Modified/If-Modified-Since
Last-Modified/If-Modified-Since要配合Cache-Control使用。
Last-Modified:響應資源的最后修改時間。
If-Modified-Since:當緩存過期時,發現資源具有Last-Modified聲明,則在請求頭帶上If-Modified-Since(值就是Last-Modified)。服務器收到請求后發現有頭If-Modified-Since則與被請求資源的最后修改時間進行比對。若最后修改時間較新,說明資源又被改動過,則響應HTTP 200整片資源內容(寫在響應消息包體內);若最后修改時間較舊,說明資源無新修改,則響應HTTP 304,告知瀏覽器繼續使用所保存的cache。
Etag/If-None-Match
Etag/If-None-Match也要配合Cache-Control使用。
Etag:資源在服務器的唯一標識(生成規則由服務器決定)。Apache中,ETag的值,默認是對文件的索引節(INode),大小(Size)和最后修改時間(MTime)進行Hash后得到的。
If-None-Match:當緩存過期時,發現資源具有Etage聲明,則在請求頭帶上If-None-Match(值就是Etag)。服務器收到請求后發現有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決定返回200或304。
前端控制禁止緩存:
1、在html 頭部加上如下代碼:
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="0">
這樣所有的js 文件都不會被緩存。
2、清楚form表單里的臨時緩存
<body onLoad="javascript:document.yourFormName.reset()">
yourFormName :表單名字
其實form表單的緩存對於我們書寫還是有幫助的,一般情況不建議清理,但是有時候為了安全問題等,需要清理一下!
3、清除ajax緩存
1.url地址上加上隨機數
url參數后加上"?ran="+Math.random;//ran隨便取
2、加上時間戳
"?timestamp=" + new Date().getTime();
服務端禁止:
在服務端加 header("Cache-Control: no-cache, must-revalidate")
參考:https://www.haorooms.com/post/js_llq_hc/
https://mp.weixin.qq.com/s?__biz=MjM5OTMxMzA4NQ==&mid=400875941&idx=2&sn=46101bbc366233024289492eaefa0e77&scene=21#wechat_redirect