摘要:在此,我會(huì)嘗試用簡(jiǎn)單明了的文字,像大家系統(tǒng)的介紹緩存機(jī)制,期望對(duì)各位正確的理解前端緩存有所幫助。兩類緩存規(guī)則可以同時(shí)存在,強(qiáng)制緩存優(yōu)先級(jí)高于對(duì)比緩存,也就是說,當(dāng)執(zhí)行強(qiáng)制緩存的規(guī)則時(shí),如果緩存生效,直接使用緩存,不再執(zhí)行對(duì)比緩存規(guī)則。
前言
在請(qǐng)求一個(gè)靜態(tài)文件的時(shí)候(圖片,css,js)等,這些文件的特點(diǎn)是文件不經(jīng)常變化,將這些不經(jīng)常變化的文件存儲(chǔ)起來,對(duì)客戶端來說是一個(gè)優(yōu)化用戶瀏覽體驗(yàn)的方法。那么這個(gè)就是客戶端緩存的意義了。
Http 緩存機(jī)制作為 web 性能優(yōu)化的重要手段,對(duì)于從事 Web 開發(fā)的同學(xué)們來說,應(yīng)該是知識(shí)體系庫(kù)中的一個(gè)基礎(chǔ)環(huán)節(jié),同時(shí)對(duì)于有志成為前端架構(gòu)師的同學(xué)來說是必備的知識(shí)技能。
但是對(duì)于很多前端同學(xué)來說,僅僅只是知道瀏覽器會(huì)對(duì)請(qǐng)求的靜態(tài)文件進(jìn)行緩存,但是為什么被緩存,緩存是怎樣生效的,卻并不是很清楚。
在此,我會(huì)嘗試用簡(jiǎn)單明了的文字,像大家系統(tǒng)的介紹HTTP緩存機(jī)制,期望對(duì)各位正確的理解前端緩存有所幫助。
緩存規(guī)則解析HTTP緩存有多種規(guī)則,根據(jù)是否需要重新向服務(wù)器發(fā)起請(qǐng)求來分類,我將其分為兩大類(強(qiáng)制緩存,對(duì)比緩存)
在詳細(xì)介紹這兩種規(guī)則之前,先通過時(shí)序圖的方式,讓大家對(duì)這兩種規(guī)則有個(gè)簡(jiǎn)單了解。
已存在緩存數(shù)據(jù)時(shí),僅基于強(qiáng)制緩存,請(qǐng)求數(shù)據(jù)的流程如下:
已存在緩存數(shù)據(jù)時(shí),僅基于對(duì)比緩存,請(qǐng)求數(shù)據(jù)的流程如下:
對(duì)緩存機(jī)制不太了解的同學(xué)可能會(huì)問,基于對(duì)比緩存的流程下,不管是否使用緩存,都需要向服務(wù)器發(fā)送請(qǐng)求,那么還用緩存干什么?
這個(gè)問題,我們暫且放下,后文在詳細(xì)介紹每種緩存規(guī)則的時(shí)候,會(huì)帶給大家答案。
我們可以看到兩類緩存規(guī)則的不同,強(qiáng)制緩存如果生效,不需要再和服務(wù)器發(fā)生交互,而對(duì)比緩存不管是否生效,都需要與服務(wù)端發(fā)生交互。
兩類緩存規(guī)則可以同時(shí)存在,強(qiáng)制緩存優(yōu)先級(jí)高于對(duì)比緩存,也就是說,當(dāng)執(zhí)行強(qiáng)制緩存的規(guī)則時(shí),如果緩存生效,直接使用緩存,不再執(zhí)行對(duì)比緩存規(guī)則。
強(qiáng)制緩存從上文我們得知,強(qiáng)制緩存,在緩存數(shù)據(jù)未失效的情況下,可以直接使用緩存數(shù)據(jù),那么瀏覽器是如何判斷緩存數(shù)據(jù)是否失效呢?
我們知道,在沒有緩存數(shù)據(jù)的時(shí)候,瀏覽器向服務(wù)器請(qǐng)求數(shù)據(jù)時(shí),服務(wù)器會(huì)將數(shù)據(jù)和緩存規(guī)則一并返回,緩存規(guī)則信息包含在響應(yīng)header中。
對(duì)于強(qiáng)制緩存來說,響應(yīng)header中會(huì)有兩個(gè)字段來標(biāo)明失效規(guī)則(Expires/Cache-Control)使用chrome的開發(fā)者工具,可以很明顯的看到對(duì)于強(qiáng)制緩存生效時(shí),網(wǎng)絡(luò)請(qǐng)求的情況。
Expires
Expires的值為服務(wù)端返回的到期時(shí)間,即下一次請(qǐng)求時(shí),請(qǐng)求時(shí)間小于服務(wù)端返回的到期時(shí)間,直接使用緩存數(shù)據(jù)。
不過Expires 是HTTP 1.0的東西,現(xiàn)在默認(rèn)瀏覽器均默認(rèn)使用HTTP 1.1,所以它的作用基本忽略。
另一個(gè)問題是,到期時(shí)間是由服務(wù)端生成的,但是客戶端時(shí)間可能跟服務(wù)端時(shí)間有誤差,這就會(huì)導(dǎo)致緩存命中的誤差。
所以HTTP 1.1 的版本,使用Cache-Control替代。
Cache-Control
Cache-Control 是最重要的規(guī)則。常見的取值有private、public、no-cache、max-age,no-store,默認(rèn)為private。
private: 客戶端可以緩存 public: 客戶端和代理服務(wù)器都可緩存(前端的同學(xué),可以認(rèn)為public和private是一樣的) max-age=xxx: 緩存的內(nèi)容將在 xxx 秒后失效 no-cache: 需要使用對(duì)比緩存來驗(yàn)證緩存數(shù)據(jù)(后面介紹) no-store: 所有內(nèi)容都不會(huì)緩存,強(qiáng)制緩存,對(duì)比緩存都不會(huì)觸發(fā)
(對(duì)于前端開發(fā)來說,緩存越多越好,so...基本上和它說886)
舉個(gè)例子:
圖中Cache-Control僅指定了max-age,所以默認(rèn)為private,緩存時(shí)間為31536000秒(365天)也就是說,在365天內(nèi)再次請(qǐng)求這條數(shù)據(jù),都會(huì)直接獲取緩存數(shù)據(jù)庫(kù)中的數(shù)據(jù),直接使用。
沒懂的話,我們換通俗一點(diǎn)的話來說一遍。當(dāng)客戶端第一次訪問資源的時(shí)候,服務(wù)端在返回資源內(nèi)容的同時(shí)也返回了Expires: Sun, 16 Oct 2016 05:43:02 GMT。
服務(wù)端告訴瀏覽器: 你Y的先把這個(gè)文件給我緩存起來,在這個(gè)過期時(shí)間之前,這個(gè)文件都不會(huì)變化了,你下次需要這個(gè)文件的時(shí)候,你就不要過來找我要了,你就去緩存中拿就好了,又快又好。
瀏覽器回答說:諾。
于是在第二次html頁(yè)面中又要訪問這個(gè)資源的時(shí)候,并且訪問的日期在Sun, 16 Oct 2016 05:43:02 GMT之前,瀏覽器就不去服務(wù)器那邊獲取文件了,自己從緩存中自食其力了。
但是呢,瀏覽器畢竟是在客戶端的,客戶端的時(shí)間可是不準(zhǔn)確的,用戶可以隨著自己的喜好修改自己機(jī)器的時(shí)間,比如我把我機(jī)器的時(shí)間調(diào)成Sun, 16 Oct 2016 05:43:03 GMT,那么呢?我的瀏覽器就不會(huì)再使用緩存了,而每次都去服務(wù)器獲取文件。于是,服務(wù)器怒了:給你個(gè)絕對(duì)時(shí)間,你由于環(huán)境被修改沒法判斷過期,那么我就給你相對(duì)時(shí)間吧。于是就返回了Cache-Control: max-age:600,瀏覽器你給我緩存?zhèn)€10分鐘去。于是瀏覽器只有乖乖的緩存10分鐘了。
但是問題又來了,如果有的服務(wù)器同時(shí)設(shè)置了Expires和Cache-Control怎么辦呢?(不是閑的沒事干,而是由于Cache-Controll是HTTP1.1中才有的)那么就是根據(jù)更先進(jìn)的設(shè)置Cache-Control來為標(biāo)準(zhǔn)。
好了,現(xiàn)在有個(gè)問題,我有個(gè)文件可能時(shí)不時(shí)會(huì)更新,服務(wù)端非常希望客戶端能時(shí)不時(shí)過來問一下這個(gè)文件是否過期,如果沒有過期,服務(wù)端不返回?cái)?shù)據(jù)給你,只告訴瀏覽器你的緩存還沒有過期(304)。然后瀏覽器使用自己存儲(chǔ)的緩存來做顯示。這個(gè)就叫做條件請(qǐng)求。
對(duì)比緩存對(duì)比緩存,顧名思義,需要進(jìn)行比較判斷是否可以使用緩存。瀏覽器第一次請(qǐng)求數(shù)據(jù)時(shí),服務(wù)器會(huì)將緩存標(biāo)識(shí)與數(shù)據(jù)一起返回給客戶端,客戶端將二者備份至緩存數(shù)據(jù)庫(kù)中。
再次請(qǐng)求數(shù)據(jù)時(shí),客戶端將備份的緩存標(biāo)識(shí)發(fā)送給服務(wù)器,服務(wù)器根據(jù)緩存標(biāo)識(shí)進(jìn)行判斷,判斷成功后,返回304狀態(tài)碼,通知客戶端比較成功,可以使用緩存數(shù)據(jù)。
對(duì)于對(duì)比緩存來說,緩存標(biāo)識(shí)的傳遞是我們著重需要理解的,它在請(qǐng)求header和響應(yīng)header間進(jìn)行傳遞,一共分為兩種標(biāo)識(shí)傳遞,接下來,我們分開介紹。
Last-Modified / If-Modified-Since
Last-Modified:服務(wù)器在響應(yīng)請(qǐng)求時(shí),告訴瀏覽器資源的最后修改時(shí)間。
If-Modified-Since:
再次請(qǐng)求服務(wù)器時(shí),通過此字段通知服務(wù)器上次請(qǐng)求時(shí),服務(wù)器返回的資源最后修改時(shí)間。
服務(wù)器收到請(qǐng)求后發(fā)現(xiàn)有頭If-Modified-Since 則與被請(qǐng)求資源的最后修改時(shí)間進(jìn)行比對(duì)。
若資源的最后修改時(shí)間大于If-Modified-Since,說明資源又被改動(dòng)過,則響應(yīng)整片資源內(nèi)容,返回狀態(tài)碼200;若資源的最后修改時(shí)間小于或等于If-Modified-Since,說明資源無新修改,則響應(yīng)HTTP 304,告知瀏覽器繼續(xù)使用所保存的cache。
Etag / If-None-Match(優(yōu)先級(jí)高于Last-Modified / If-Modified-Since)
第一次客戶端訪問資源的時(shí)候,服務(wù)端返回資源內(nèi)容的同時(shí)返回了ETag:1234,告訴客戶端:這個(gè)文件的標(biāo)簽是1234,我如果修改了我這邊的資源的話,這個(gè)標(biāo)簽就會(huì)不一樣了。
第二次客戶端訪問資源的時(shí)候,由于緩存中已經(jīng)有了Etag為1234的資源,客戶端要去服務(wù)端查詢的是這個(gè)資源有木有過期呢?所以帶上了If-None-Match: 1234。告訴服務(wù)端:如果你那邊的資源還是1234標(biāo)簽的資源,你就返回304告訴我,不需要返回資源內(nèi)容了。如果不是的話,你再返回資源內(nèi)容給我就行了。服務(wù)端就比較下Etag來看是返回304還是200。
各種刷新理解了上面的緩存標(biāo)簽之后就很好理解各種刷新了。
刷新有三種
瀏覽器中寫地址,回車 F5 Ctrl+F5
假設(shè)對(duì)一個(gè)資源:
瀏覽器第一次訪問,獲取資源內(nèi)容和cache-control: max-age:600,Last_Modify: Wed, 10 Aug 2013 15:32:18 GMT于是瀏覽器把資源文件放到緩存中,并且決定下次使用的時(shí)候直接去緩存中取了。
瀏覽器url回車
瀏覽器發(fā)現(xiàn)緩存中有這個(gè)文件了,好了,就不發(fā)送任何請(qǐng)求了,直接去緩存中獲取展現(xiàn)。(最快)
下面我按下了F5刷新
F5就是告訴瀏覽器,別偷懶,好歹去服務(wù)器看看這個(gè)文件是否有過期了。于是瀏覽器就膽膽襟襟的發(fā)送一個(gè)請(qǐng)求帶上If-Modify-since:Wed, 10 Aug 2013 15:32:18 GMT
然后服務(wù)器發(fā)現(xiàn):誒,這個(gè)文件我在這個(gè)時(shí)間后還沒修改過,不需要給你任何信息了,返回304就行了。于是瀏覽器獲取到304后就去緩存中歡歡喜喜獲取資源了。
但是呢,下面我們按下了Ctrl+F5
這個(gè)可是要命了,告訴瀏覽器,你先把你緩存中的這個(gè)文件給我刪了,然后再去服務(wù)器請(qǐng)求個(gè)完整的資源文件下來。于是客戶端就完成了強(qiáng)行更新的操作...
還有說一下,那個(gè)ETag實(shí)際上很少人使用,因?yàn)樗挠?jì)算是使用算法來得出的,而算法會(huì)占用服務(wù)端計(jì)算的資源,所有服務(wù)端的資源都是寶貴的,所以就很少使用etag了。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/61880.html
摘要:在此,我會(huì)嘗試用簡(jiǎn)單明了的文字,像大家系統(tǒng)的介紹緩存機(jī)制,期望對(duì)各位正確的理解前端緩存有所幫助。兩類緩存規(guī)則可以同時(shí)存在,強(qiáng)制緩存優(yōu)先級(jí)高于對(duì)比緩存,也就是說,當(dāng)執(zhí)行強(qiáng)制緩存的規(guī)則時(shí),如果緩存生效,直接使用緩存,不再執(zhí)行對(duì)比緩存規(guī)則。 前言 在請(qǐng)求一個(gè)靜態(tài)文件的時(shí)候(圖片,css,js)等,這些文件的特點(diǎn)是文件不經(jīng)常變化,將這些不經(jīng)常變化的文件存儲(chǔ)起來,對(duì)客戶端來說是一個(gè)優(yōu)化用戶瀏覽體...
摘要:對(duì)于瀏覽器緩存,相信很多開發(fā)者對(duì)它真的是又愛又恨。那么瀏覽器緩存究竟是個(gè)什么樣的神奇玩意呢什么是瀏覽器緩存簡(jiǎn)單來說,瀏覽器緩存就是把一個(gè)已經(jīng)請(qǐng)求過的資源如頁(yè)面,圖片,,數(shù)據(jù)等拷貝一份副本儲(chǔ)存在瀏覽器中。 對(duì)于瀏覽器緩存,相信很多開發(fā)者對(duì)它真的是又愛又恨。一方面極大地提升了用戶體驗(yàn),而另一方面有時(shí)會(huì)因?yàn)樽x取了緩存而展示了錯(cuò)誤的東西,而在開發(fā)過程中千方百計(jì)地想把緩存禁掉。那么瀏覽器緩存究竟...
摘要:對(duì)于瀏覽器緩存,相信很多開發(fā)者對(duì)它真的是又愛又恨。那么瀏覽器緩存究竟是個(gè)什么樣的神奇玩意呢什么是瀏覽器緩存簡(jiǎn)單來說,瀏覽器緩存就是把一個(gè)已經(jīng)請(qǐng)求過的資源如頁(yè)面,圖片,,數(shù)據(jù)等拷貝一份副本儲(chǔ)存在瀏覽器中。 對(duì)于瀏覽器緩存,相信很多開發(fā)者對(duì)它真的是又愛又恨。一方面極大地提升了用戶體驗(yàn),而另一方面有時(shí)會(huì)因?yàn)樽x取了緩存而展示了錯(cuò)誤的東西,而在開發(fā)過程中千方百計(jì)地想把緩存禁掉。那么瀏覽器緩存究竟...
摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
閱讀 3120·2021-10-18 13:33
閱讀 863·2019-08-30 14:20
閱讀 2650·2019-08-30 13:14
閱讀 2542·2019-08-29 18:38
閱讀 2907·2019-08-29 16:44
閱讀 1234·2019-08-29 15:23
閱讀 3525·2019-08-29 13:28
閱讀 1934·2019-08-28 18:00