瀏覽器快取對於前端一點都不陌生,最常見的就是,新版本上線了,測試卻說這怎麼還沒有變化呢?使用 ctr + F5 強制重新整理之後,立馬就好了。或者清除瀏覽器快取,按住ctr+shift+delete,彈出如圖:
我們會發現目前瀏覽器快取的圖片和檔案的大小。或者進入chrome://chrome-urls/找到chrome://cache/ 就可以看到所有快取的地址列表。對於瀏覽器快取,前端對它是又愛又恨,有時想保留,有時想禁掉,所以看看瀏覽器快取到底是怎樣的?
一、什麼是瀏覽器快取?
瀏覽器快取就是瀏覽器根據 url 第一次訪問網站之後,將網站的 html、css、js、圖片等檔案複製一份保留到瀏覽器中,當你二次訪問這個 url 的網站時,如果網站沒有明確表示有更新時,瀏覽器直接在快取中查詢內容,不會再次請求網頁內容,只有網頁明確表示有更新時,瀏覽器才會向伺服器發起網路請求,再次下載網頁。
如上圖,百度首頁就是使用了快取機制,首次訪問之後 web資源被快取,在後面重復請求中,資源直接在快取中讀取,而不是向伺服器請求資源。
二、為什麼使用快取?
2.1、為什麼很多網站二次開啟速度很快?
網頁二次開啟很快,主要原因是第一次載入頁面過程中,快取了部分耗時資料,這一現象,對於單頁面應用開發非常明顯。
上一篇文章《瀏覽器工作原理》中,瀏覽器工作流程介紹,輸入網址回車以後瀏覽器向伺服器發起服務之前,會現在瀏覽器快取中查詢是否有需要的檔案?如果有則直接在快取中獲取檔案,避免向伺服器請求和下載檔案,所以節省了一部分時間。
2.2、瀏覽器快取優點
1、減少網路頻寬消耗
對於網站運營者或者訪問網頁的使用者,頻寬就代表著 money ,過多的消耗頻寬,我們伺服器配置就得升級,使用瀏覽器快取之後,就會減少網路流量,降低運營成本。
2、降低伺服器壓力
使用瀏覽器快取之後,除第一次訪問需要向伺服器請求網站全部資源,後續訪問可以重複使用瀏覽器本地快取,減少對伺服器的請求,間接降低伺服器的壓力,同時,搜尋引擎的爬蟲也會根據快取過期機制降低抓取的頻率,也可以降低伺服器壓力。
3、減少網路延遲,加快網頁載入
瀏覽器快取 web資源後,減少網路請求,可以更快速地獲取到伺服器返回資料,同時使用瀏覽器快取內的檔案比伺服器獲取快很多,所以網頁載入速度明顯快很多。
三、瀏覽器的快取規則
對於瀏覽器端的快取來講,這些規則是在 http 協議和 meta 標籤中定義的。分別從兩個維度:新鮮度和校驗值,規定瀏覽器是否可以直接使用快取中的副本,還是直接從伺服器獲取最新資源。
3.1、新鮮度(過期):瀏覽器快取的有效期,快取必須滿足以下兩個條件,瀏覽器才會認為是最新的,可以直接使用。
- 含有完整的過期時間控制頭資訊,並在有效期內。
- 瀏覽器已經使用過這個副本,並且在會話中已經檢查過新鮮度。
3.2、校驗值(驗證):伺服器返回資源的時候,會在響應頭資訊中帶上資源實體標籤 Entity Tag,可以用來作為瀏覽器再次請求過程的校驗標識,如果發現校驗標識不匹配,說明資源已經被修改過或過期,瀏覽器需要重新請求資源。
四、如何控制快取?
快取規則可以設定在html的meta標籤,也可以設定在http協議頭內。
4.1、前端 html 中 meta 標籤
在 html 頁面中加入快取設定,程式碼如下:
<meta http-equiv="Pragma" content="no-cache" />
<!-- Pragma是http1.0版本中給客戶端設定快取方式之一 -->
上邊程式碼,禁止瀏覽器快取,瀏覽器每次訪問網頁都要去伺服器請求。事實這種禁用快取形式作用有限:
- 只有IE瀏覽器才能標識這段 meta 的含義,其他主流瀏覽器僅認識 “Cache-Control:no-store” 的 meta 標籤。
- 在IE瀏覽器中,並不一定新增 pragma,但是會讓當前網頁每次都會向伺服器傳送請求。
4.2、HTTP協議頭
http請求和響應頭中,與快取相關的常見型別:
規則 |
訊息報頭 |
值/示例 |
型別 |
作用 |
新鮮度 |
Pragma |
no-cache |
響應 |
告訴瀏覽器忽略資源的快取副本,每次訪問都需要去伺服器拉取【http1.0中存在的欄位,在http1.1已被拋棄,使用Cache-Control替代,但為了做http協議的向下相容,很多網站依舊會帶上這個欄位】 |
|
Expires |
Mon, 15 Aug 2016 03:56:47 GMT |
響應 |
啟用快取和定義快取時間。告訴瀏覽器資源快取過期時間,如果還沒過該時間點則不發請求【http1.0中存在的欄位,該欄位所定義的快取時間是相對伺服器上的時間而言的,如果客戶端上的時間跟伺服器上的時間不一致(特別是使用者修改了自己電腦的系統時間),那快取時間可能就沒啥意義了。在HTTP 1.1版開始,使用Cache-Control: max-age=秒替代】 |
|
Cache-Control |
no-cache |
響應 |
告訴瀏覽器忽略資源的快取副本,強制每次請求直接傳送給伺服器,拉取資源,但不是“不快取” |
|
|
no-store |
響應 |
強制快取在任何情況下都不要保留任何副本 |
|
|
max-age=[秒] |
響應 |
指明快取副本的有效時長,從請求時間開始到過期時間之間的秒數 |
|
|
public |
響應 |
任何路徑的快取者(本地快取、代理伺服器),可以無條件的快取該資源 |
|
|
private |
響應 |
只針對單個使用者或者實體(不同使用者、視窗)快取資源 |
|
Last-Modified |
Mon, 15 Aug 2016 03:56:47 GMT |
響應 |
告訴瀏覽器這個資源最後的修改時間。伺服器將資源傳遞給客戶端時,會將資源最後更改的時間以“Last-Modified: GMT”的形式加在實體首部上一起返回給客戶端【只能精確到秒級,如果某些檔案在1秒鐘以內,被修改多次的話,它將不能準確標註檔案的修改時間】 |
|
If-Modified-Since |
Mon, 15 Aug 2016 03:56:47 GMT |
請求 |
其值為上次響應頭的Last-Modified值,再次向web伺服器請求時帶上頭If-Modified-Since。web伺服器收到請求後發現有頭If-Modified-Since則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說明資源又被改動過,則響應整片資源內容(寫在響應訊息包體內),包括更新Last-Modified的值,HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應HTTP 304(無需請求,節省瀏覽),告知瀏覽器繼續使用所儲存的cache |
校驗值 |
ETag |
"fd56273325a2114818df4f29a628226d" |
響應 |
告訴瀏覽器當前資源在伺服器的唯一識別符號(生成規則由伺服器決定) |
|
If-None-Match |
"fd56273325a2114818df4f29a628226d" |
請求 |
當資源過期時(使用Cache-Control標識的max-age),發現資源具有Etage宣告,則再次向web伺服器請求時帶上頭If-None-Match(Etag的值)。web伺服器收到請求後發現有頭If-None-Match則與被請求資源的相應校驗串進行比對,決定返回200或304 |
各種型別之間的關係和區別:
- Cache-Control 與 Expires:它兩作用一樣,都表明當前資源的有效期,控制瀏覽器是取快取還是直接向伺服器獲取,Cache-Control可以設定的更細緻,如果同時設定,它的優先順序高於Expires。
- Last-Modified / ETag 與 Cache-Control / Expires:配置Last-Modified/ETag的情況下,瀏覽器再次訪問URL的資源,還是會傳送請求到伺服器,詢問檔案是否已經修改,如果沒有,伺服器會給瀏覽器返回304,瀏覽器直接從本地快取中取就好了,反之,伺服器會直接向瀏覽器返回資料。Cache-Control / Expires 檢測本地快取是否還在有效期內,在有效期內,直接使用本地快取,阻止傳送請求。如果同時設定,Cache-Control / Expiress 優先順序更高。一般情況下,兩者配合使用,因為即使伺服器設定快取時間, 當使用者點選“重新整理”按鈕時,瀏覽器會忽略快取繼續向伺服器傳送請求,這時Last-Modified/ETag將能夠很好利用304,從而減少響應開銷。
- Last-Modified 與 ETag:ETag主要是為了解決Last-Modified比較難解決的問題:1、Last-Modified標註的最後修改只能精確到秒級,如果某些檔案在1秒鐘以內,被修改多次的話,它將不能準確標註檔案的新鮮度。2、如果某些檔案會被定期生成,當有時內容並沒有任何變化,但Last-Modified卻改變了,導致檔案沒法使用快取。3、有可能存在伺服器沒有準確獲取檔案修改時間,或者與代理伺服器時間不一致等情形。ETag是伺服器自動生成或開發者生成對應資源在伺服器的唯一識別符號,能夠更加精準控制快取。兩者可以一起使用,伺服器優先驗證ETag,一致時,才會繼續比對Last-Mofifed,才決定是否要返回304。
五、不能快取的請求
並不是所有的請求都能被快取,無法被快取的有:
- post 請求無法被快取。
- 需要根據cookie、認證資訊等決定輸入內容的動態請求不能被快取。
- http響應頭中不包含Last-Modified/ETag,也不包含Cache-Control/Expiress的請求無法被快取。
- http資訊頭明確設定Cache-Control:no-cache,pragma:no-cache或Cache-Control:max-age=0瀏覽器不快取時。