前端緩存大全

前言

緩存可以說是性能優(yōu)化中簡(jiǎn)單高效的一種優(yōu)化方式了。一個(gè)優(yōu)秀的緩存策略可以縮短網(wǎng)頁請(qǐng)求資源的速度烟阐,減少延遲搬俊,并且由于緩存文件可以重復(fù)利用紊扬,還可以減少帶寬,降低網(wǎng)絡(luò)負(fù)荷唉擂。根據(jù)緩存的不同可以分為http緩存和瀏覽器緩存(本地緩存)餐屎。


http緩存

對(duì)于一個(gè)資源請(qǐng)求來說,可以分為發(fā)起網(wǎng)絡(luò)請(qǐng)求玩祟、后端處理腹缩、瀏覽器響應(yīng)三個(gè)步驟。http緩存可以幫助我們?cè)诘谝粋€(gè)和第三個(gè)步驟中優(yōu)化性能空扎。比如強(qiáng)緩存是直接使用緩存而不發(fā)起請(qǐng)求藏鹊,協(xié)商緩存是發(fā)起了請(qǐng)求但如果請(qǐng)求后端的資源沒有改變,那么就不需要再將數(shù)據(jù)返回转锈,這樣就減少了響應(yīng)時(shí)間盘寡。

接下來的內(nèi)容中我們將通過緩存位置、緩存策略以及實(shí)際場(chǎng)景應(yīng)用緩存策略來探討瀏覽器緩存機(jī)制撮慨。

緩存位置

從緩存位置上來說分為四種竿痰,并且各自有優(yōu)先級(jí),當(dāng)依次查找緩存且都沒有命中的時(shí)候才會(huì)去請(qǐng)求網(wǎng)絡(luò)砌溺。

  • Service Worker
  • Memory Cache
  • Disk Cache
  • Push Cache

Service Worker

Service Worker 是運(yùn)行在瀏覽器背后的獨(dú)立線程影涉,一般可以用來實(shí)現(xiàn)緩存功能。使用 Service Worker的話抚吠,傳輸協(xié)議必須為 HTTPS常潮。

Memory Cache

Memory Cache 也就是內(nèi)存中的緩存,主要包含的是當(dāng)前中頁面中已經(jīng)抓取到的資源楷力,例如頁面上已經(jīng)下載的樣式喊式、腳本、圖片等萧朝。讀取內(nèi)存中的數(shù)據(jù)肯定比硬盤快岔留,內(nèi)存緩存雖然讀取高效,可是緩存持續(xù)性很短检柬,會(huì)隨著進(jìn)程的釋放而釋放献联。 一旦我們關(guān)閉 Tab 頁面,內(nèi)存中的緩存也就被釋放了何址,而且內(nèi)存容量要比硬盤小的多里逆。

當(dāng)我們?cè)L問過頁面以后,再次刷新頁面用爪,可以發(fā)現(xiàn)很多數(shù)據(jù)都來自于內(nèi)存緩存

WX20210730-142350@2x.png

需要注意的事情是原押,內(nèi)存緩存在緩存資源時(shí)并不關(guān)心返回資源的HTTP緩存頭Cache-Control是什么值,同時(shí)資源的匹配也并非僅僅是對(duì)URL做匹配偎血,還可能會(huì)對(duì)Content-Type诸衔,CORS等其他特征做校驗(yàn)盯漂。

Disk Cache

Disk Cache 也就是存儲(chǔ)在硬盤中的緩存,讀取速度慢點(diǎn)笨农,但是什么都能存儲(chǔ)到硬盤中就缆,比之 Memory Cache 勝在容量和存儲(chǔ)時(shí)效性上。

在所有瀏覽器緩存中谒亦,Disk Cache 覆蓋面基本是最大的竭宰。它會(huì)根據(jù) HTTP頭部字段判斷哪些資源需要緩存,哪些資源可以不請(qǐng)求直接使用诊霹,哪些資源已經(jīng)過期需要重新請(qǐng)求羞延。并且即使在跨站點(diǎn)的情況下,相同地址的資源一旦被硬盤緩存下來脾还,就不會(huì)再次去請(qǐng)求數(shù)據(jù)。絕大部分的緩存都來自 Disk Cache入愧,關(guān)于 HTTP 的協(xié)議頭中的緩存字段鄙漏,我們會(huì)在下文進(jìn)行詳細(xì)介紹。

瀏覽器會(huì)把哪些文件丟進(jìn)內(nèi)存中棺蛛?哪些丟進(jìn)硬盤中?
關(guān)于這點(diǎn),網(wǎng)上說法不一哩俭,不過以下觀點(diǎn)比較靠得捉时摹:

  • 對(duì)于大文件來說,大概率是不存儲(chǔ)在內(nèi)存中的终畅,反之優(yōu)先
  • 當(dāng)前系統(tǒng)內(nèi)存使用率高的話籍胯,文件優(yōu)先存儲(chǔ)進(jìn)硬盤

Push Cache

Push Cache(推送緩存)是 HTTP/2 中的內(nèi)容,當(dāng)以上三種緩存都沒有命中時(shí)离福,它才會(huì)被使用杖狼。它只在會(huì)話(Session)中存在,一旦會(huì)話結(jié)束就被釋放妖爷,并且緩存時(shí)間也很短暫蝶涩,在Chrome瀏覽器中只有5分鐘左右,同時(shí)它也并非嚴(yán)格執(zhí)行HTTP頭中的緩存指令絮识。

如果以上四種緩存都沒有命中的話绿聘,那么只能發(fā)起請(qǐng)求來獲取資源了。

那么為了性能上的考慮次舌,大部分的接口都應(yīng)該選擇好緩存策略熄攘,通常http緩存策略分為兩種:強(qiáng)緩存和協(xié)商緩存,并且緩存策略都是通過設(shè)置 HTTP Header 來實(shí)現(xiàn)的垃它。

緩存過程分析

瀏覽器與服務(wù)器通信的方式為應(yīng)答模式:瀏覽器發(fā)起HTTP請(qǐng)求---服務(wù)器響應(yīng)該請(qǐng)求鲜屏,那么瀏覽器怎么確定一個(gè)資源該不該緩存烹看,如何去緩存呢?瀏覽器第一次向服務(wù)器發(fā)起請(qǐng)求拿到請(qǐng)求結(jié)果后洛史,將請(qǐng)求結(jié)果和緩存標(biāo)識(shí)存入瀏覽器緩存惯殊,瀏覽器對(duì)于緩存的處理是根據(jù)請(qǐng)求資源時(shí)返回的響應(yīng)頭來確定。具體過程如下圖:


由上圖我們可以知道:

  • http每次發(fā)起請(qǐng)求,都會(huì)先在瀏覽器緩存中查找該請(qǐng)求的結(jié)果以及緩存標(biāo)識(shí)
  • 瀏覽器每次拿到請(qǐng)求結(jié)果和緩存標(biāo)識(shí)都會(huì)存入瀏覽器緩存中
    以上兩點(diǎn)就是http緩存機(jī)制的關(guān)鍵也殖,它確保了每個(gè)請(qǐng)求的緩存存入和讀取土思,只要我們理解http緩存的使用規(guī)則,那么所有的問題就會(huì)迎刃而解了忆嗜,本文也將圍繞著這點(diǎn)進(jìn)行詳細(xì)分析己儒。為了方便大家理解,這里我們根據(jù)是否需要向服務(wù)器重新發(fā)起HTTP請(qǐng)求將緩存分為強(qiáng)緩存和協(xié)商緩存捆毫。

強(qiáng)緩存

不會(huì)向服務(wù)器發(fā)送請(qǐng)求闪湾,直接從緩存中讀取資源,在chrome控制臺(tái)的Network選項(xiàng)中可以看到該請(qǐng)求返回200狀態(tài)碼绩卤,并且size顯示from disk cache或from memory cache途样。強(qiáng)緩存可以通過設(shè)置兩種HTTP Header實(shí)現(xiàn):Expires和Cache-Control。

Expires

緩存過期時(shí)間濒憋,Expires=請(qǐng)求日期何暇,它告訴瀏覽器在過期日期前瀏覽器可以直接從瀏覽器緩存讀取數(shù)據(jù)而無需再次請(qǐng)求。

Expires是HTTP/1.0的產(chǎn)物凛驮,受限于客戶端時(shí)間裆站,如果服務(wù)器和客戶端時(shí)間偏差較大,可能會(huì)造成緩存失效黔夭。Expires: Wed, 22 Oct 2018 08:41:00 GMT表示資源會(huì)在 Wed, 22 Oct 2018 08:41:00 GMT 后過期宏胯,需要再次請(qǐng)求。

Cache-Control

主要用于控制網(wǎng)頁緩存纠修。例如Cache-Control:max-age=300胳嘲,表示這個(gè)請(qǐng)求在5分鐘內(nèi)(瀏覽器也會(huì)記錄下來)再次加載資源,就會(huì)命中強(qiáng)緩存扣草。

Cache-Control可以在請(qǐng)求頭或響應(yīng)頭中設(shè)置,并且可以組合使用多種指令:


Expires和Cache-Control兩者對(duì)比

其實(shí)兩者差別不大了牛,區(qū)別在于Expires是http1.0的產(chǎn)物,Cache-Control是http1.1的產(chǎn)物辰妙,兩者同時(shí)存在的話鹰祸,Cache-Control優(yōu)先級(jí)高于Expires;在某些不支持http1.1的環(huán)境下密浑,Expires就會(huì)發(fā)揮用處蛙婴。所以Expires其實(shí)是過時(shí)的產(chǎn)物,現(xiàn)階段它的存在只是一種兼容性的寫法尔破。

強(qiáng)緩存判斷是否命中的依據(jù)來自于是否超出某個(gè)時(shí)間或者某個(gè)時(shí)間段街图,而不關(guān)心服務(wù)器文件是否已經(jīng)更新浇衬,這可能會(huì)導(dǎo)致加載文件不是服務(wù)端最新的內(nèi)容,那我們?nèi)绾潍@知服務(wù)端內(nèi)容是否已經(jīng)發(fā)生了更新呢餐济?此時(shí)我們需要用到協(xié)商緩存策略耘擂。

協(xié)商緩存

協(xié)商緩存就是強(qiáng)緩存失效后,瀏覽器攜帶緩存標(biāo)識(shí)向服務(wù)器發(fā)起請(qǐng)求絮姆,由服務(wù)器決定瀏覽器是否使用瀏覽器緩存的過程醉冤,主要有以下兩種情況:

  • 協(xié)商緩存生效,返回304和Not Modified


  • 協(xié)商緩存失效,返回200和請(qǐng)求結(jié)果


協(xié)商緩存可以通過設(shè)置兩種 HTTP Header實(shí)現(xiàn): Last-Modified和ETag.

Last-Modified和If-Modified-Since

瀏覽器在第一次請(qǐng)求服務(wù)器時(shí),服務(wù)器在返回資源的同時(shí)篙悯,會(huì)在響應(yīng)頭中添加Last-Modified蚁阳,值是這個(gè)資源在服務(wù)器上的最后修改時(shí)間,瀏覽器接收后緩存文件和Last-Modified這個(gè)響應(yīng)頭鸽照;

Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT

瀏覽器下一次請(qǐng)求這個(gè)資源螺捐,會(huì)檢測(cè)Last-Modified這個(gè)header,于是添加If-Modified-Since這個(gè)header矮燎,值就是Last-Modified中的值归粉,服務(wù)器再次收到這個(gè)資源請(qǐng)求,會(huì)根據(jù)If-Modified-Since中的值與服務(wù)器中這個(gè)資源的最后修改時(shí)間對(duì)比漏峰,如果沒有變化,返回304和空的響應(yīng)體届榄,瀏覽器直接從緩存讀取浅乔,如果If-Modified-Since的時(shí)間與服務(wù)器中這個(gè)資源的最后修改時(shí)間不一致說明文件有更新,于是返回新的資源文件和200铝条。

但是Last-Modified存在一些弊端:

  • 如果本地打開緩存文件靖苇,即使沒有對(duì)文件進(jìn)行修改,但還是會(huì)造成Last-Modified被修改班缰,服務(wù)端不能命中緩存導(dǎo)致發(fā)送相同的資源贤壁。
  • 因?yàn)長ast-Modified只能以秒計(jì)時(shí),如果在1s內(nèi)修改了文件埠忘,那么服務(wù)端還是會(huì)認(rèn)為資源被命中了脾拆,不會(huì)返回最新的資源。

既然根據(jù)文件修改時(shí)間來決定是否命中緩存有缺陷,能否可以直接根據(jù)文件內(nèi)容是否修改來決定緩存策略?所以在HTTP/1.1出現(xiàn)了Etag和If-None-Match

Etag和If-None-Match

Etag是服務(wù)器響應(yīng)請(qǐng)求時(shí)返回當(dāng)前資源文件的一個(gè)唯一標(biāo)識(shí)(由服務(wù)器生成),只有資源發(fā)生變化,Etag就會(huì)重新生成莹妒。瀏覽器在下一次加載資源向服務(wù)器發(fā)送請(qǐng)求時(shí)名船,會(huì)將上一次返回的Etag值放到請(qǐng)求頭里的If-None-Match里,服務(wù)器只需要比較客戶端傳來的If-None-Match跟自己服務(wù)器上資源的Etag是否一致旨怠,就能判斷資源是否修改過渠驼。如果一致則直接返回304告知客戶端直接使用本地緩存即可,如果不一致那么返回新的資源文件和200(當(dāng)然也包括 了 新的Etag)發(fā)給客戶端鉴腻。


兩者對(duì)比

  • 首先在精度上迷扇,Etag要優(yōu)于Last-Modified:Last-Modified的時(shí)間單位是秒百揭,如果某個(gè)文件在1秒內(nèi)被修改了,那么服務(wù)端還是會(huì)認(rèn)為資源被命中了蜓席,不會(huì)返回最新的資源器一。
  • 第二在性能上,Last-Modified要優(yōu)于Etag瓮床,畢竟Last-Modified只需要記錄時(shí)間盹舞,而Etag需要服務(wù)器通過算法計(jì)算出一個(gè)hash值。
  • 第三在優(yōu)先級(jí)上隘庄,服務(wù)器校驗(yàn)優(yōu)先考慮Etag踢步。

緩存機(jī)制

強(qiáng)制緩存優(yōu)先于協(xié)商緩存進(jìn)行,若強(qiáng)制緩存(Expires和Cache-Control)生效則直接使用緩存丑掺,若不生效則進(jìn)行協(xié)商緩存(Last-Modified / If-Modified-Since和Etag / If-None-Match)获印,協(xié)商緩存由服務(wù)器決定是否使用緩存,若協(xié)商緩存失效街州,那么代表該請(qǐng)求的緩存失效兼丰,返回200,重新返回資源和緩存標(biāo)識(shí)唆缴,再存入瀏覽器緩存中鳍征;生效則返回304,繼續(xù)使用緩存面徽,具體流程如下:


看到這里,不知道你是否存在這樣一個(gè)疑問:如果什么緩存策略都沒設(shè)置,那么瀏覽器怎么處理?

對(duì)于這種情況,瀏覽器會(huì)采用一個(gè)啟發(fā)式的算法,通常會(huì)取響應(yīng)頭中Date減去Last-Modified值的10%作為緩存時(shí)間.

實(shí)際場(chǎng)景應(yīng)用緩存策略

頻繁變動(dòng)的資源

Cache-Control:no-cache

對(duì)于頻繁變動(dòng)的資源艳丛,首先需要設(shè)置Cache-Control:no-cache 使用協(xié)商緩存。這樣的做法雖然不能節(jié)省請(qǐng)求數(shù)量趟紊,但是能顯著減少響應(yīng)資源時(shí)間氮双。

不常變化的資源

Cache-Control: max-age=31536000

通常在處理這類資源時(shí),給它們的 Cache-Control 配置一個(gè)很大的 max-age=31536000 (一年)霎匈,這樣瀏覽器之后請(qǐng)求相同的 URL 會(huì)命中強(qiáng)制緩存戴差。而為了解決更新的問題,就需要在文件名(或者路徑)中添加 hash铛嘱, 版本號(hào)等動(dòng)態(tài)字符暖释,之后更改動(dòng)態(tài)字符,從而達(dá)到更改引用 URL 的目的弄痹,讓之前的強(qiáng)制緩存失效 (其實(shí)并未立即失效饭入,只是不再使用了而已)。
在線提供的類庫 (如 jquery-3.3.1.min.js, lodash.min.js 等) 均采用這個(gè)模式肛真。

用戶行為對(duì)瀏覽器緩存的影響

所謂用戶行為對(duì)瀏覽器緩存的影響,指的是用戶在瀏覽器如何操作時(shí),會(huì)觸發(fā)怎樣的緩存策略,主要有3種:

  • 打開網(wǎng)頁,地址欄輸入地址: 查找disk cache中是否有匹配.如有則使用;沒有則發(fā)送網(wǎng)絡(luò)請(qǐng)求
  • 普通刷新(F5): 因?yàn)門AB并沒有關(guān)閉谐丢,memory cache是可用的,會(huì)被優(yōu)先使用(如果匹配的話),其次才是disk cache
  • 強(qiáng)制刷新(Ctrl+F5):瀏覽器不使用緩存,因此發(fā)送的請(qǐng)求頭部均帶有Cache-Control: no-cache(為了兼容,還帶了Pragma: no-cache),服務(wù)器直接返回200和最新內(nèi)容。

**`總結(jié):

  • 強(qiáng)緩存和協(xié)商緩存是根據(jù)HTTP Headers來決定使用哪一種乾忱,緩存的位置有可能是內(nèi)存(memory cache)也有可能是硬盤(disk cache)
  • 常見的HTTP緩存只能緩存GET請(qǐng)求響應(yīng)的資源讥珍,對(duì)于其他類型的響應(yīng)則無能為力,所以說的請(qǐng)求緩存都是指GET請(qǐng)求窄瘟。`*

瀏覽器緩存

http://www.reibang.com/writer#/notebooks/50529144/notes/90020625/preview

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末衷佃,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蹄葱,更是在濱河造成了極大的恐慌氏义,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件图云,死亡現(xiàn)場(chǎng)離奇詭異惯悠,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)竣况,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門克婶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丹泉,“玉大人摹恨,你說我怎么就攤上這事筋岛∩购澹” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵揩晴,是天一觀的道長。 經(jīng)常有香客問我硫兰,道長劫映,這世上最難降的妖魔是什么泳赋? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮千诬,結(jié)果婚禮上徐绑,老公的妹妹穿的比我還像新娘傲茄。我一直安慰自己盘榨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著弛饭,像睡著了一般侣颂。 火紅的嫁衣襯著肌膚如雪憔晒。 梳的紋絲不亂的頭發(fā)上拒担,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音低零,去河邊找鬼掏婶。 笑死雄妥,一個(gè)胖子當(dāng)著我的面吹牛茎芭,可吹牛的內(nèi)容都是我干的梅桩。 我是一名探鬼主播趁仙,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼盏袄!你這毒婦竟也來了辕羽?” 一聲冷哼從身側(cè)響起刁愿,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎脑题,沒想到半個(gè)月后旭蠕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辆它。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锰茉。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡片吊,死狀恐怖俏脊,靈堂內(nèi)的尸體忽然破棺而出爷贫,到底是詐尸還是另有隱情漫萄,我是刑警寧澤卷胯,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站担钮,受9級(jí)特大地震影響箫津,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜田炭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一叨吮、第九天 我趴在偏房一處隱蔽的房頂上張望茶鉴。 院中可真熱鬧涵叮,春花似錦围肥、人聲如沸穆刻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诚些。三九已至,卻和暖如春绞吁,著一層夾襖步出監(jiān)牢的瞬間家破,已是汗流浹背汰聋。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留韭邓,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓鸭你,卻偏偏與公主長得像袱巨,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嫉入,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容