自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

瀏覽器緩存原理總結(jié)

系統(tǒng) 瀏覽器
瀏覽器在加載資源時,先根據(jù)這個資源的一些http header判斷它是否命中強緩存,強緩存如果命中,瀏覽器直接從自己的緩存中讀取資源,不會發(fā)請求到服務(wù)器。

一、瀏覽器緩存基本認(rèn)識

分為強緩存和協(xié)商緩存

  1. 瀏覽器在加載資源時,先根據(jù)這個資源的一些http header判斷它是否***強緩存,強緩存如果***,瀏覽器直接從自己的緩存中讀取資源,不會發(fā)請求到服務(wù)器。比如某個css文件,如果瀏覽器在加載它所在的網(wǎng)頁時,這個css文件的緩存配置***了強緩存,瀏覽器就直接從緩存中加載這個css,連請求都不會發(fā)送到網(wǎng)頁所在服務(wù)器
  2. 當(dāng)強緩存沒有***的時候,瀏覽器一定會發(fā)送一個請求到服務(wù)器,通過服務(wù)器端依據(jù)資源的另外一些http header驗證這個資源是否***協(xié)商緩存,如果協(xié)商緩存***,服務(wù)器會將這個請求返回,但是不會返回這個資源的數(shù)據(jù),而是告訴客戶端可以直接從緩存中加載這個資源,于是瀏覽器就又會從自己的緩存中去加載這個資源
  3. 強緩存與協(xié)商緩存的共同點是:如果***,都是從客戶端緩存中加載資源,而不是從服務(wù)器加載資源數(shù)據(jù);區(qū)別是:強緩存不發(fā)請求到服務(wù)器,協(xié)商緩存會發(fā)請求到服務(wù)器
  4. 當(dāng)協(xié)商緩存也沒有***的時候,瀏覽器直接從服務(wù)器加載資源數(shù)據(jù)

二、強緩存的原理

2.1 介紹

當(dāng)瀏覽器對某個資源的請求***了強緩存時,返回的http狀態(tài)為200,在chrome的開發(fā)者工具的network里面size會顯示為from cache,比如京東的首頁里就有很多靜態(tài)資源配置了強緩存,用chrome打開幾次,再用f12查看network,可以看到有不少請求就是從緩存中加載的 

image.png

強緩存是利用Expires或者Cache-Control這兩個http response header實現(xiàn)的,它們都用來表示資源在客戶端緩存的有效期。

Expires是http1.0提出的一個表示資源過期時間的header,它描述的是一個絕對時間,由服務(wù)器返回,用GMT格式的字符串表示,如:Expires:Thu, 31 Dec 2037 23:55:55 GMT

2.2 Expires緩存原理

  • 瀏覽器***次跟服務(wù)器請求一個資源,服務(wù)器在返回這個資源的同時,在respone的header加上Expires,如 
image.png
  • 瀏覽器在接收到這個資源后,會把這個資源連同所有response header一起緩存下來(所以緩存***的請求返回的header并不是來自服務(wù)器,而是來自之前緩存的header)
  • 瀏覽器再請求這個資源時,先從緩存中尋找,找到這個資源后,拿出它的Expires跟當(dāng)前的請求時間比較,如果請求時間在Expires指定的時間之前,就能***緩存,否則就不行
  • 如果緩存沒有***,瀏覽器直接從服務(wù)器加載資源時,Expires Header在重新加載的時候會被更新

Expires是較老的強緩存管理header,由于它是服務(wù)器返回的一個絕對時間,在服務(wù)器時間與客戶端時間相差較大時,緩存管理容易出現(xiàn)問題,比如隨意修改下客戶端時間,就能影響緩存***的結(jié)果。所以在http1.1的時候,提出了一個新的header,就是Cache-Control,這是一個相對時間,在配置緩存的時候,以秒為單位,用數(shù)值表示,如:Cache-Control:max-age=315360000

2.3 Cache-Control緩存原理

瀏覽器***次跟服務(wù)器請求一個資源,服務(wù)器在返回這個資源的同時,在respone的header加上Cache-Control,如: 

image.png
  1. 瀏覽器在接收到這個資源后,會把這個資源連同所有response header一起緩存下來
  2. 瀏覽器再請求這個資源時,先從緩存中尋找,找到這個資源后,根據(jù)它***次的請求時間和Cache-Control設(shè)定的有效期,計算出一個資源過期時間,再拿這個過期時間跟當(dāng)前的請求時間比較,如果請求時間在過期時間之前,就能***緩存,否則就不行
  3. 如果緩存沒有***,瀏覽器直接從服務(wù)器加載資源時,Cache-Control Header在重新加載的時候會被更新

Cache-Control描述的是一個相對時間,在進(jìn)行緩存***的時候,都是利用客戶端時間進(jìn)行判斷,所以相比較Expires,Cache-Control的緩存管理更有效,安全一些。

這兩個header可以只啟用一個,也可以同時啟用,當(dāng)response header中,Expires和Cache-Control同時存在時,Cache-Control優(yōu)先級高于Expires: 

image.png

三、強緩存的管理

前面介紹的是強緩存的原理,在實際應(yīng)用中我們會碰到需要強緩存的場景和不需要強緩存的場景,通常有2種方式來設(shè)置是否啟用強緩存

  • 通過代碼的方式,在web服務(wù)器返回的響應(yīng)中添加Expires和Cache-Control Header
  • 通過配置web服務(wù)器的方式,讓web服務(wù)器在響應(yīng)資源的時候統(tǒng)一添加Expires和Cache-Control Header

比如在javaweb里面,我們可以使用類似下面的代碼設(shè)置強緩存 

  1. java.util.Date date = new java.util.Date();     
  2. response.setDateHeader("Expires",date.getTime()+20000); //Expires:過時期限值  
  3. response.setHeader("Cache-Control""public"); //Cache-Control來控制頁面的緩存與否,public:瀏覽器和緩存服務(wù)器都可以緩存頁面信息; 
  4. response.setHeader("Pragma""Pragma"); //Pragma:設(shè)置頁面是否緩存,為Pragma則緩存,no-cache則不緩存 

還可以通過類似下面的java代碼設(shè)置不啟用強緩存 

  1. response.setHeader( "Pragma""no-cache" );    
  2. response.setDateHeader("Expires", 0);    
  3. response.addHeader( "Cache-Control""no-cache" );//瀏覽器和緩存服務(wù)器都不應(yīng)該緩存頁面信息 

nginx和apache作為專業(yè)的web服務(wù)器,都有專門的配置文件,可以配置expires和cache-control,這方面的知識,如果你對運維感興趣的話,可以在百度上搜索nginx 設(shè)置 expires cache-control或 apache 設(shè)置 expires cache-control 都能找到不少相關(guān)的文章。

由于在開發(fā)的時候不會專門去配置強緩存,而瀏覽器又默認(rèn)會緩存圖片,css和js等靜態(tài)資源,所以開發(fā)環(huán)境下經(jīng)常會因為強緩存導(dǎo)致資源沒有及時更新而看不到***的效果,解決這個問題的方法有很多,常用的有以下幾種

  • 處理緩存帶來的問題
  • 直接ctrl+f5,這個辦法能解決頁面直接引用的資源更新的問題
  • 使用瀏覽器的隱私模式開發(fā)

如果用的是chrome,可以f12在network那里把緩存給禁掉(這是個非常有效的方法) 

image.png

在開發(fā)階段,給資源加上一個動態(tài)的參數(shù),如css/index.css?v=0.0001,由于每次資源的修改都要更新引用的位置,同時修改參數(shù)的值,所以操作起來不是很方便,除非你是在動態(tài)頁面比如jsp里開發(fā)就可以用服務(wù)器變量來解決(v=${sysRnd}),或者你能用一些前端的構(gòu)建工具來處理這個參數(shù)修改的問題

如果資源引用的頁面,被嵌入到了一個iframe里面,可以在iframe的區(qū)域右鍵單擊重新加載該頁面,以chrome為例 

image.png

如果緩存問題出現(xiàn)在ajax請求中,最有效的解決辦法就是ajax的請求地址追加隨機數(shù)

還有一種情況就是動態(tài)設(shè)置iframe的src時,有可能也會因為緩存問題,導(dǎo)致看不到***的效果,這時候在要設(shè)置的src后面添加隨機數(shù)也能解決問題

如果你用的是grunt和gulp、webpack這種前端工具開發(fā),通過它們的插件比如grunt-contrib-connect來啟動一個靜態(tài)服務(wù)器,則完全不用擔(dān)心開發(fā)階段的資源更新問題,因為在這個靜態(tài)服務(wù)器下的所有資源返回的respone header中,cache-control始終被設(shè)置為不緩存 

image.png

四、強緩存的應(yīng)用

強緩存是前端性能優(yōu)化最有力的工具,沒有之一,對于有大量靜態(tài)資源的網(wǎng)頁,一定要利用強緩存,提高響應(yīng)速度。通常的做法是,為這些靜態(tài)資源全部配置一個超時時間超長的Expires或Cache-Control,這樣用戶在訪問網(wǎng)頁時,只會在***次加載時從服務(wù)器請求靜態(tài)資源,其它時候只要緩存沒有失效并且用戶沒有強制刷新的條件下都會從自己的緩存中加載,比如前面提到過的京東首頁緩存的資源,它的緩存過期時間都設(shè)置到了2026年 

image.png

然而這種緩存配置方式會帶來一個新的問題,就是發(fā)布時資源更新的問題,比如某一張圖片,在用戶訪問***個版本的時候已經(jīng)緩存到了用戶的電腦上,當(dāng)網(wǎng)站發(fā)布新版本,替換了這個圖片時,已經(jīng)訪問過***個版本的用戶由于緩存的設(shè)置,導(dǎo)致在默認(rèn)的情況下不會請求服務(wù)器***的圖片資源,除非他清掉或禁用緩存或者強制刷新,否則就看不到***的圖片效果

這個問題已經(jīng)有成熟的解決方案,具體內(nèi)容可閱讀知乎這篇文章詳細(xì)了解:http://www.zhihu.com/question/20790576

文章提到的東西都屬于理論上的解決方案,不過現(xiàn)在已經(jīng)有很多前端工具能夠?qū)嶋H地解決這個問題,由于每個工具涉及到的內(nèi)容細(xì)節(jié)都有很多,本文沒有辦法一一深入介紹。有興趣的可以去了解下grunt gulp webpack fis 還有edp這幾個工具,基于這幾個工具都能解決這個問題,尤其是fis和edp是百度推出的前端開發(fā)平臺,有現(xiàn)成的文檔可以參考:

  • http://fis.baidu.com/fis3/api/index.html
  • http://ecomfe.github.io/edp/doc/initialization/install/

強緩存還有一點需要注意的是,通常都是針對靜態(tài)資源使用,動態(tài)資源需要慎用,除了服務(wù)端頁面可以看作動態(tài)資源外,那些引用靜態(tài)資源的html也可以看作是動態(tài)資源,如果這種html也被緩存,當(dāng)這些html更新之后,可能就沒有機制能夠通知瀏覽器這些html有更新,尤其是前后端分離的應(yīng)用里,頁面都是純html頁面,每個訪問地址可能都是直接訪問html頁面,這些頁面通常不加強緩存,以保證瀏覽器訪問這些頁面時始終請求服務(wù)器***的資源

五、協(xié)商緩存的原理

5.1 介紹

當(dāng)瀏覽器對某個資源的請求沒有***強緩存,就會發(fā)一個請求到服務(wù)器,驗證協(xié)商緩存是否***,如果協(xié)商緩存***,請求響應(yīng)返回的http狀態(tài)為304并且會顯示一個Not Modified的字符串,比如你打開京東的首頁,按f12打開開發(fā)者工具,再按f5刷新頁面,查看network,可以看到有不少請求就是***了協(xié)商緩存的 

image.png

查看單個請求的Response Header,也能看到304的狀態(tài)碼和Not Modified的字符串,只要看到這個就可說明這個資源是***了協(xié)商緩存,然后從客戶端緩存中加載的,而不是服務(wù)器***的資源 

image.png

5.2 Last-Modified,If-Modified-Since控制協(xié)商緩存

瀏覽器***次跟服務(wù)器請求一個資源,服務(wù)器在返回這個資源的同時,在respone的header加上Last-Modified的header,這個header表示這個資源在服務(wù)器上的***修改時間 

image.png

瀏覽器再次跟服務(wù)器請求這個資源時,在request的header上加上If-Modified-Since的header,這個header的值就是上一次請求時返回的Last-Modified的值 

image.png

服務(wù)器再次收到資源請求時,根據(jù)瀏覽器傳過來If-Modified-Since和資源在服務(wù)器上的***修改時間判斷資源是否有變化,如果沒有變化則返回304 Not Modified,但是不會返回資源內(nèi)容;如果有變化,就正常返回資源內(nèi)容。當(dāng)服務(wù)器返回304 Not Modified的響應(yīng)時,response header中不會再添加Last-Modified的header,因為既然資源沒有變化,那么Last-Modified也就不會改變,這是服務(wù)器返回304時的response header 

image.png

瀏覽器收到304的響應(yīng)后,就會從緩存中加載資源

如果協(xié)商緩存沒有***,瀏覽器直接從服務(wù)器加載資源時,Last-Modified Header在重新加載的時候會被更新,下次請求時,If-Modified-Since會啟用上次返回的Last-Modified值

【Last-Modified,If-Modified-Since】都是根據(jù)服務(wù)器時間返回的header,一般來說,在沒有調(diào)整服務(wù)器時間和篡改客戶端緩存的情況下,這兩個header配合起來管理協(xié)商緩存是非??煽康?,但是有時候也會服務(wù)器上資源其實有變化,但是***修改時間卻沒有變化的情況,而這種問題又很不容易被定位出來,而當(dāng)這種情況出現(xiàn)的時候,就會影響協(xié)商緩存的可靠性。所以就有了另外一對header來管理協(xié)商緩存,這對header就是【ETag、If-None-Match】。它們的緩存管理的方式是

5.3 ETag、If-None-Match控制協(xié)商緩存

瀏覽器***次跟服務(wù)器請求一個資源,服務(wù)器在返回這個資源的同時,在respone的header加上ETag的header,這個header是服務(wù)器根據(jù)當(dāng)前請求的資源生成的一個唯一標(biāo)識,這個唯一標(biāo)識是一個字符串,只要資源有變化這個串就不同,跟***修改時間沒有關(guān)系,所以能很好的補充Last-Modified的問題 

image.png

瀏覽器再次跟服務(wù)器請求這個資源時,在request的header上加上If-None-Match的header,這個header的值就是上一次請求時返回的ETag的值 

image.png

服務(wù)器再次收到資源請求時,根據(jù)瀏覽器傳過來If-None-Match和然后再根據(jù)資源生成一個新的ETag,如果這兩個值相同就說明資源沒有變化,否則就是有變化;如果沒有變化則返回304 Not Modified,但是不會返回資源內(nèi)容;如果有變化,就正常返回資源內(nèi)容。與Last-Modified不一樣的是,當(dāng)服務(wù)器返回304 Not Modified的響應(yīng)時,由于ETag重新生成過,response header中還會把這個ETag返回,即使這個ETag跟之前的沒有變化 

image.png

瀏覽器收到304的響應(yīng)后,就會從緩存中加載資源。

六、協(xié)商緩存的管理

協(xié)商緩存跟強緩存不一樣,強緩存不發(fā)請求到服務(wù)器,所以有時候資源更新了瀏覽器還不知道,但是協(xié)商緩存會發(fā)請求到服務(wù)器,所以資源是否更新,服務(wù)器肯定知道。大部分web服務(wù)器都默認(rèn)開啟協(xié)商緩存,而且是同時啟用【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】,比如apache: 

image.png

如果沒有協(xié)商緩存,每個到服務(wù)器的請求,就都得返回資源內(nèi)容,這樣服務(wù)器的性能會極差。

【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】一般都是同時啟用,這是為了處理Last-Modified不可靠的情況。

有一種場景需要注意

  • 分布式系統(tǒng)里多臺機器間文件的Last-Modified必須保持一致,以免負(fù)載均衡到不同機器導(dǎo)致比對失敗;
  • 分布式系統(tǒng)盡量關(guān)閉掉ETag(每臺機器生成的ETag都會不一樣);

京東頁面的資源請求,返回的repsones header就只有Last-Modified,沒有ETag: 

image.png

協(xié)商緩存需要配合強緩存使用,你看前面這個截圖中,除了Last-Modified這個header,還有強緩存的相關(guān)header,因為如果不啟用強緩存的話,協(xié)商緩存根本沒有意義

七、相關(guān)瀏覽器行為對緩存的影響

如果資源已經(jīng)被瀏覽器緩存下來,在緩存失效之前,再次請求時,默認(rèn)會先檢查是否***強緩存,如果強緩存***則直接讀取緩存,如果強緩存沒有***則發(fā)請求到服務(wù)器檢查是否***協(xié)商緩存,如果協(xié)商緩存***,則告訴瀏覽器還是可以從緩存讀取,否則才從服務(wù)器返回***的資源。這是默認(rèn)的處理方式,這個方式可能被瀏覽器的行為改變:

當(dāng)ctrl+f5強制刷新網(wǎng)頁時,直接從服務(wù)器加載,跳過強緩存和協(xié)商緩存;

當(dāng)f5刷新網(wǎng)頁時,跳過強緩存,但是會檢查協(xié)商緩存

責(zé)任編輯:未麗燕 來源: Poetry's Blog
相關(guān)推薦

2018-11-30 09:00:19

html5cssjavascript

2022-03-24 08:31:25

Web性能優(yōu)化瀏覽器緩存API封裝

2015-10-27 13:37:14

瀏覽器HTTP緩存

2017-04-26 14:15:35

瀏覽器緩存機制

2020-11-06 15:20:45

瀏覽器前端架構(gòu)

2018-08-07 10:44:50

緩存技術(shù)瀏覽器

2011-05-06 09:36:16

動態(tài)頁面

2021-06-01 09:12:47

前端瀏覽器緩存

2020-07-16 08:04:21

瀏覽器緩存策略

2021-08-02 13:05:49

瀏覽器HTTP前端

2013-05-23 16:01:56

瀏覽器

2020-12-29 09:56:29

瀏覽器緩存HTTP

2017-05-15 13:40:20

瀏覽器http緩存機制

2020-10-29 11:04:28

緩存瀏覽器LocalStorag

2013-06-14 13:56:29

瀏覽器渲染原理

2012-02-01 13:42:19

2022-08-30 09:01:11

瀏覽器渲染前端

2021-04-19 11:40:15

瀏覽器路徑

2020-03-11 20:42:34

瀏覽器緩存機制

2019-08-16 10:54:03

本地存儲javascripthttp緩存
點贊
收藏

51CTO技術(shù)棧公眾號