淺談前端緩存(轉至大佬)


前端緩存

前端緩存可分為兩大類:http緩存和瀏覽器緩存。我們今天重點講的是http緩存,所以關於瀏覽器緩存大家自行去查閱。下面這張圖是前端緩存的一個大致知識點:


 
image

HTTP緩存

首先是解決困擾人們的老大難問題:

一、什么是HTTP緩存 ?

http緩存指的是: 當客戶端向服務器請求資源時,會先抵達瀏覽器緩存,如果瀏覽器有“要請求資源”的副本,就可以直接從瀏覽器緩存中提取而不是從原始服務器中提取這個資源。

常見的http緩存只能緩存get請求響應的資源,對於其他類型的響應則無能為力,所以后續說的請求緩存都是指GET請求。

http緩存都是從第二次請求開始的。第一次請求資源時,服務器返回資源,並在respone header頭中回傳資源的緩存參數;第二次請求時,瀏覽器判斷這些請求參數,命中強緩存就直接200,否則就把請求參數加到request header頭中傳給服務器,看是否命中協商緩存,命中則返回304,否則服務器會返回新的資源。

1、http緩存的分類:
根據是否需要重新向服務器發起請求來分類,可分為(強制緩存,協商緩存) 根據是否可以被單個或者多個用戶使用來分類,可分為(私有緩存,共享緩存) 強制緩存如果生效,不需要再和服務器發生交互,而協商緩存不管是否生效,都需要與服務端發生交互。下面是強制緩存和協商緩存的一些對比:

 
image

1.1、強制緩存
強制緩存在緩存數據未失效的情況下(即Cache-Control的max-age沒有過期或者Expires的緩存時間沒有過期),那么就會直接使用瀏覽器的緩存數據,不會再向服務器發送任何請求。強制緩存生效時,http狀態碼為200。這種方式頁面的加載速度是最快的,性能也是很好的,但是在這期間,如果服務器端的資源修改了,頁面上是拿不到的,因為它不會再向服務器發請求了。這種情況就是我們在開發種經常遇到的,比如你修改了頁面上的某個樣式,在頁面上刷新了但沒有生效,因為走的是強緩存,所以Ctrl + F5一頓操作之后就好了。 跟強制緩存相關的header頭屬性有(Pragma/Cache-Control/Expires)
 
image

這個Pragma和Cache-Control共存時的優先級問題還有點異議,我在不同的文章里發現:有的說Pragma的優先級更高,有的說Cache-Control高。為了搞清楚這個問題,我決定動手操作一波,首先我用nodejs搭建后台服務器,目的是設置緩存參數,具體代碼如下:
 
image

然后再瀏覽器上訪問: http://localhost:8888
第一次訪問時都是從后台返回的數據:
 
image

 

第二次訪問時:


 
image
 
image

最終得出結論:
Pragma和Cache-control共存時,Pragma的優先級是比Cache-Control高的。

注意:
在chrome瀏覽器中返回的200狀態會有兩種情況:
1、from memory cache
(從內存中獲取/一般緩存更新頻率較高的js、圖片、字體等資源)

2、from disk cache
(從磁盤中獲取/一般緩存更新頻率較低的js、css等資源)

這兩種情況是chrome自身的一種緩存策略,這也是為什么chrome瀏覽器響應的快的原因。其他瀏覽返回的是已緩存狀態,沒有標識是從哪獲取的緩存。

chrome瀏覽器:


 
image

Firefox瀏覽器:


 
image

1.2、協商緩存
當第一次請求時服務器返回的響應頭中沒有Cache-Control和Expires或者Cache-Control和Expires過期還或者它的屬性設置為no-cache時(即不走強緩存),那么瀏覽器第二次請求時就會與服務器進行協商,與服務器端對比判斷資源是否進行了修改更新。如果服務器端的資源沒有修改,那么就會返回304狀態碼,告訴瀏覽器可以使用緩存中的數據,這樣就減少了服務器的數據傳輸壓力。如果數據有更新就會返回200狀態碼,服務器就會返回更新后的資源並且將緩存信息一起返回。跟協商緩存相關的header頭屬性有(ETag/If-Not-Match 、Last-Modified/If-Modified-Since)請求頭和響應頭需要成對出現

 
image

協商緩存的執行流程是這樣的:當瀏覽器第一次向服務器發送請求時,會在響應頭中返回協商緩存的頭屬性:ETag和Last-Modified,其中ETag返回的是一個hash值,Last-Modified返回的是GMT格式的最后修改時間。然后瀏覽器在第二次發送請求的時候,會在請求頭中帶上與ETag對應的If-Not-Match,其值就是響應頭中返回的ETag的值,Last-Modified對應的If-Modified-Since。服務器在接收到這兩個參數后會做比較,如果返回的是304狀態碼,則說明請求的資源沒有修改,瀏覽器可以直接在緩存中取數據,否則,服務器會直接返回數據。
 
image

 
image

 

注意:
ETag/If-Not-Match是在HTTP/1.1出現的,主要是解決以下問題:

(1)、Last-Modified標注的最后修改只能精確到秒級,如果某些文件在1秒鍾以內,被修改多次的話,它將不能准確標注文件的修改時間

(2)、如果某些文件被修改了,但是內容並沒有任何變化,而Last-Modified卻改變了,導致文件沒法使用緩存

(3)、有可能存在服務器沒有准確獲取文件修改時間,或者與代理服務器時間不一致等情形

1.3、私有緩存(瀏覽器級緩存)
私有緩存只能用於單獨的用戶:Cache-Control: Private

1.4、共享緩存(代理級緩存)
共享緩存可以被多個用戶使用: Cache-Control: Public

二、為什么要使用HTTP緩存 ?

根據上面的學習可發現使用緩存的好處主要有以下幾點:
1. 減少了冗余的數據傳輸,節省了網費。
2. 緩解了服務器的壓力, 大大提高了網站的性能
3. 加快了客戶端加載網頁的速度

三、如何使用HTTP緩存 ?

一般需要緩存的資源有html頁面和其他靜態資源:
1、html頁面緩存的設置主要是在<head>標簽中嵌入<meta>標簽,這種方式只對頁面有效,對頁面上的資源無效
1.1、html頁面禁用緩存的設置如下:
<meta http-equiv="pragma" content="no-cache">
// 僅有IE瀏覽器才識別的標簽,不一定會在請求字段加上Pragma,但的確會讓當前頁面每次都發新請求
<meta http-equiv="cache-control" content="no-cache">
// 其他主流瀏覽器識別的標簽
<meta http-equiv="expires" content="0">
// 僅有IE瀏覽器才識別的標簽,該方式僅僅作為知會IE緩存時間的標記,你並不能在請求或響應報文中找到Expires字段

1.2、html設置緩存如下:
<meta http-equiv="Cache-Control" content="max-age=7200" />
// 其他主流瀏覽器識別的標簽
<meta http-equiv="Expires" content="Mon, 20 Aug 2018 23:00:00 GMT" />
// 僅有IE瀏覽器才識別的標簽

2、靜態資源的緩存一般是在web服務器上配置的,常用的web服務器有:nginx、apache。具體的配置這里不做詳細介紹,大家自行查閱。

3、不想使用緩存的幾種方式:
3.1、Ctrl + F5強制刷新,都會直接向服務器提取數據。
3.2、按F5刷新或瀏覽器的刷新按鈕,默認加上Cache-Control:max-age=0,即會走協商緩存。
3.2、在IE瀏覽器下不想使用緩存的做法:打開IE,點擊工具欄上的工具->Internet選項->常規->瀏覽歷史記錄 設置. 選擇“從不”,然后保存。最后點擊“刪除”把Internet臨時文件都刪掉 (IE緩存的文件就是Internet臨時文件)。
3.3、還有就是上面1、2中禁用緩存的做法
3.4、對於其他瀏覽器也都有清除緩存的辦法

四、HTTP緩存的幾個注意點

1、強緩存情況下,只要緩存還沒過期,就會直接從緩存中取數據,就算服務器端有數據變化,也不會從服務器端獲取了,這樣就無法獲取到修改后的數據。決解的辦法有:在修改后的資源加上隨機數,確保不會從緩存中取。

例如:
http://www.kimshare.club/kim/common.css?v=22324432
http://www.kimshare.club/kim/common.2312331.css

2、盡量減少304的請求,因為我們知道,協商緩存每次都會與后台服務器進行交互,所以性能上不是很好。從性能上來看盡量多使用強緩存。

3、在Firefox瀏覽器下,使用Cache-Control: no-cache 是不生效的,其識別的是no-store。這樣能達到其他瀏覽器使用Cache-Control: no-cache的效果。所以為了兼容Firefox瀏覽器,經常會寫成Cache-Control: no-cache,no-store。

4、與緩存相關的幾個header屬性有:Vary、Date/Age。
Vary:
vary本身是“變化”的意思,而在http報文中更趨於是“vary from”(與。。。不同)的含義,它表示服務端會以什么基准字段來區分、篩選緩存版本。
在服務端有着這么一個地址,如果是IE用戶則返回針對IE開發的內容,否則返回另一個主流瀏覽器版本的內容。
格式:Vary: User-Agent
知會代理服務器需要以 User-Agent 這個請求首部字段來區別緩存版本,防止傳遞給客戶端的緩存不正確。

Date/Age:
響應報文中的 Date 和 Age 字段:區分其收到的資源是否命中了代理服務器的緩存。
Date 理所當然是原服務器發送該資源響應報文的時間(GMT格式),如果你發現 Date 的時間與“當前時間”差別較大,或者連續F5刷新發現 Date 的值都沒變化,則說明你當前請求是命中了代理服務器的緩存。
Age 也是響應報文中的首部字段,它表示該文件在代理服務器中存在的時間(秒),如文件被修改或替換,Age會重新由0開始累計。

瀏覽器緩存

下面說說最常用到的瀏覽器緩存有:cookie、sessionStorage、localStorage這三者的主要特征如下:


 
image

課程總結

1、對於強制緩存,服務器通知瀏覽器一個緩存時間,在緩存時間內,下次請求,直接用緩存,不在時間內,執行協商緩存策略。
2、對於協商緩存,將緩存信息中的Etag和Last-Modified通過請求發送給服務器,由服務器校驗,返回304狀態碼時,瀏覽器直接使用緩存。

下圖是瀏覽器首次和再次發送http請求的執行流程圖:

 
image

 
image


作者:kimshare
鏈接:https://www.jianshu.com/p/227cee9c8d15
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM