HTTP前端優(yōu)化之壓縮與緩存

現(xiàn)代的瀏覽器以及服務(wù)器都支持壓縮技術(shù)哥放,唯一需要協(xié)商的是采用的壓縮算法歼指。 為了選擇采用的壓縮算法,瀏覽器和服務(wù)器之間會使用?主動協(xié)商機(jī)制

瀏覽器發(fā)送?Accept-Encoding?首部婶芭,(其中包含它所支持的壓縮算法东臀,以及各自優(yōu)先級)

服務(wù)器則從中選擇一種,使用該算法對響應(yīng)消息主體進(jìn)行壓縮犀农,并且發(fā)送?Content-Encoding首部來告知瀏覽器它使用了哪一種算法

由于該內(nèi)容協(xié)商過程是基于編碼類型來選擇資源的展現(xiàn)形式的惰赋,在響應(yīng)中,?Vary?(渲染引擎)首部中至少要包含?Accept-Encoding?;這樣,緩存服務(wù)器就可以對資源的不同的展現(xiàn)形式進(jìn)行緩存赁濒。

如果有想學(xué)習(xí)編程的初學(xué)者轨奄,可來我們的前端直播授課群的哦:733395506里面免費(fèi)送整套系統(tǒng)的前端教程!

如下圖:

也就是:

客戶端(HTTP請求頭) -------> accept-encoding: gzip,deflate,br,sdch

服務(wù)器(HTTP響應(yīng)頭) -------> content-encoding:gzip

實(shí)例

gzip(filePath, req,res, statObj) {letencoding = req.headers["accept-encoding"]if(encoding) {if(encoding.match(/gzip/)) {res.setHeader("Content-Encoding","gzip")returnzlib.createGzip()? ? ? ? ? ? }elseif(encoding.match(/deflate/)) {res.setHeader("Content-Encoding","deflate")returnzlib.createDeflate()? ? ? ? ? ? }returnfalse? ? ? ? }returnfalse? ? }letflag = this.gzip(filePath, req,res, statObj)lettype= mime.getType(filePath) ||"text/plain"res.setHeader("Content-Type",type+"; charset=utf8")if(!flag){? ? ? ? fs.createReadStream(filePath).pipe(res)? ? }else{? ? ? ? fs.createReadStream(filePath).pipe(flag).pipe(res)? ? }復(fù)制代碼

壓縮的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):減少HTTP響應(yīng)時間拒炎,提升傳輸效率

壓縮過程占用服務(wù)器額外的CPU周期挪拟,客戶端也要對壓縮文件進(jìn)行解壓縮,這也需要占用部分時間击你。

總結(jié):

請求頭:

Accept-Encoding: gzip,deflate,br,sdch玉组;告知服務(wù)器自己支持的壓縮格式

user-agent: 不同設(shè)備自動帶上這個頭,可以判斷什么樣的設(shè)備丁侄,重定向到相同的項(xiàng)目惯雳,實(shí)現(xiàn)不同設(shè)備響應(yīng)不同項(xiàng)目

響應(yīng)頭:

COntent-encoding:gzip; 告知瀏覽器,服務(wù)器使用的壓縮格式

Content-Type: 服務(wù)器給瀏覽器響應(yīng)內(nèi)容的類型

Location: 重定向到某個地方

2.緩存

假設(shè)瀏覽器存在一個緩存數(shù)據(jù)庫鸿摇,用于存儲緩存信息石景。

在客戶端第一次請求數(shù)據(jù)時,此時緩存數(shù)據(jù)庫中沒用對應(yīng)的緩存數(shù)據(jù)拙吉,需要請求服務(wù)器潮孽,服務(wù)器返回后,將數(shù)據(jù)存儲至緩存數(shù)據(jù)庫中筷黔。

HTTP緩存有多種規(guī)則往史,根據(jù)是否需要重新向服務(wù)器發(fā)起請求進(jìn)行分類 將其分為兩大類(**強(qiáng)制緩存,對比緩存又叫協(xié)商緩存)

1. 已存在緩存數(shù)據(jù)必逆,僅基于強(qiáng)制緩存怠堪,請求數(shù)據(jù)如下

2. 已存在緩存數(shù)據(jù),僅基于對比緩存名眉,請求數(shù)據(jù)如下

兩類緩存規(guī)則不同:

強(qiáng)制緩存如果生效粟矿,不需要再和服務(wù)器發(fā)生交互

對比緩存(協(xié)商緩存)不管是否生效,都需要與服務(wù)器端發(fā)生交互

**兩類緩存規(guī)則同時存在時损拢,強(qiáng)制緩存優(yōu)先級高于對比緩存陌粹,也就是說,當(dāng)執(zhí)行強(qiáng)制緩存的規(guī)則時福压,如果緩存生效掏秩,直接使用緩存,不再執(zhí)行對比緩存規(guī)則

強(qiáng)制緩存

在沒有緩存數(shù)據(jù)時荆姆,瀏覽器向服務(wù)器請求數(shù)據(jù)時蒙幻,服務(wù)器會將數(shù)據(jù)和緩存規(guī)則一并返回,?緩存規(guī)則信息包含在響應(yīng)header中?胆筒;

對于強(qiáng)制緩存來說邮破,響應(yīng)頭中會有連個字段表名失效規(guī)則(?Expires/Cache-Control?)

Expires

Expries的值為服務(wù)器端返回的到期時間诈豌,即下一次請求時,請求的時間小于服務(wù)端返回到期時間抒和,直接使用緩存數(shù)據(jù)矫渔。不過Expries是HTTP1.0的東西,現(xiàn)在瀏覽器默認(rèn)使用的是HTTP1.1摧莽,所以它的作用基本忽略

另一個問題庙洼,到期時間使用服務(wù)端生成的,但是客戶端時間可能跟服務(wù)端時間有誤差镊辕,這就導(dǎo)致了緩存命中的誤差油够,因此,HTTP1.1版本中征懈,使用了Cache-Control替代

Cache-Control

Cache-Control是最重要的規(guī)則叠聋,其常見取值:

private:客戶端可以緩存

public:客戶端和代理服務(wù)器都可緩存

max-age=xxx:緩存的內(nèi)容將在xxx秒后失效

no-cache:需要使用對比緩存來驗(yàn)證緩存數(shù)據(jù)

no-store:所有內(nèi)容都不會緩存,?強(qiáng)制緩存受裹,對比緩存都不觸發(fā)?,

實(shí)例:

圖中Cache-Control僅指定了max-age虏束,所有默認(rèn)是private棉饶,緩存時間是31536000秒(365天) 也就是說,在365天內(nèi)再次請求這條數(shù)據(jù)镇匀,都會直接獲取緩存數(shù)據(jù)庫中的數(shù)據(jù)照藻,直接使用。

對比緩存(協(xié)商緩存)

瀏覽器第一次請求數(shù)據(jù)時汗侵,服務(wù)器會將緩存標(biāo)識u數(shù)據(jù)一起返回給客戶端幸缕,客戶端將二者備份至緩存數(shù)據(jù)庫中, 再次請求數(shù)據(jù)時晰韵,客戶端將備份的數(shù)據(jù)標(biāo)識發(fā)送給服務(wù)器发乔,服務(wù)器根據(jù)緩存標(biāo)識進(jìn)行判斷,判斷成功后雪猪,返回304狀態(tài)碼栏尚,通知客戶端比較成功,可以使用緩存數(shù)據(jù)

通過兩圖對比只恨,可發(fā)現(xiàn)译仗,在對比緩存生效時,狀態(tài)碼是304官觅,并且報(bào)文大小和請求時間大大減少纵菌。 原因是,服務(wù)器在進(jìn)行標(biāo)識比較后休涤,只返回header部分咱圆,通過狀態(tài)碼通知客戶端使用緩存,不再需要將報(bào)文主體部分返回給客戶端。

緩存標(biāo)識:

Last-Modified/If-Modified-Since

Last-Modified:

服務(wù)器在響應(yīng)請求時闷堡,告訴瀏覽器資源的最后修改時間隘膘。

If-Modified-Since:

再次請求服務(wù)器時,通過此字段通知服務(wù)器上次請求時杠览,服務(wù)器返回的資源最后的修改時間弯菊。 服務(wù)器收到請求后發(fā)現(xiàn)頭有 If-Modified-Since 則與請求資源的最后修改時間進(jìn)行對比。 若資源的最后修改時間大于 If-Modified-since 踱阿,說明資源又被改動過管钳,則響應(yīng)整片資源內(nèi)容,返回狀態(tài)碼200软舌; 若資源的最后修改時間小于或等于 If-Modified-Since 才漆,說明資源沒有新修改過,則響應(yīng)HTTP304佛点,告訴繼續(xù)使用緩存中的數(shù)據(jù)

**Etag/If-None-Match

優(yōu)先級高于 Last-Modified/If-Modified-Since

Etag:

服務(wù)器響應(yīng)請求時醇滥,告訴瀏覽器當(dāng)前資源在服務(wù)器的唯一標(biāo)識(摘要)

If-None-Match:

再次請求服務(wù)器時,通過此字段通知服務(wù)器客戶端緩存數(shù)據(jù)的唯一標(biāo)識超营, 服務(wù)器收到請求后發(fā)現(xiàn)請求頭中有 If-None-Match 則與被請求資源的唯一標(biāo)識進(jìn)行比對鸳玩, 不同,說明資源又被改動過演闭,則響應(yīng)整片資源內(nèi)容不跟,返回狀態(tài)碼200; 相同米碰,說明資源沒有新修改過窝革,則響應(yīng)HTTP304,告知瀏覽器使用緩存數(shù)據(jù)

總結(jié)

對于強(qiáng)制緩存吕座,服務(wù)器通知瀏覽器一個緩存時間虐译,在緩存時間內(nèi),下次請求米诉,直接用緩存菱蔬,不在時間內(nèi),執(zhí)行比較緩存策略:

Expries/Cache-Control:max-age=xxx > Etag/If-None-Match > Last-Modified/If-Modified-Since

對于比較緩存史侣,將緩存信息中的Etage和Last-Modified通過請求發(fā)送給服務(wù)器拴泌,由服務(wù)器校驗(yàn),返回304狀態(tài)碼時惊橱,瀏覽器直接使用緩存數(shù)據(jù)蚪腐。

瀏覽器第一次請求:

瀏覽器再次請求時:

實(shí)例:

cache(filePath, req, res,statObj){letlastModified =statObj.ctime.toGMTString()letifModifiedSince = req.headers['if-modified-since']letEtag =? ? ? ? ? ? crypto.createHash("md5").update(fs.readFileSync(filePath)).digest("base64")? ? ? ? res.setHeader("Last-Modified",lastModified)? ? ? ? // Etag是響應(yīng)頭? ? ? ? res.setHeader("Etag",Etag)? ? ? ? //if-none-match 當(dāng)你修改服務(wù)器上的文件時,請求頭上面會自動添加這個頭? ? ? ? // console.log(req.headers['if-none-match'],"match")? ? ? ? // console.log(Etag)? ? ? ? //if-none-match: NISthsES8P9vzWjdFT/xyg== match? ? ? ? // console.log(req.headers['if-none-match'])? ? ? ? // T9hRJPsOY4/I9QhWp+NFlQ==? ? ? ? // 如果if-none-match存在税朴,說明你改動服務(wù)器上的文件中的內(nèi)容? ? ? ? // T9hRJPsOY4/I9QhWp+NFlQ==? ? ? ? // console.log("Etag--->",Etag)? ? ? ? // console.log("if-none-match--->",req.headers['if-none-match'])letifNoneMatch = req.headers['if-none-match']? ? ? ? // // 根據(jù)內(nèi)容摘要判斷是否需要緩存? ? ? ? //if(ifNoneMatch){? ? ? ? //? ? //ifNoneMatch說明修改了內(nèi)容? ? ? ? //? ? //returnfalse;? ? ? ? //if(ifNoneMatch !== Etag){? ? ? ? //? ? ? ? // 修改了內(nèi)容回季,并且沒恢復(fù)家制,走網(wǎng)絡(luò)? ? ? ? //returnfalse;? // 不走緩存? ? ? ? //? ? }else{? ? ? ? //? ? ? ? // 修改了內(nèi)容,并且修改完后泡一,把內(nèi)容恢復(fù)颤殴,相當(dāng)于沒有修改? ? ? ? //returntrue; // 還是從緩存中取數(shù)據(jù)? ? ? ? //? ? }? ? ? ? // }else{? ? ? ? //? ? // 說明內(nèi)容沒有改變? ? ? ? //returntrue//? ? ? ? // }? ? ? ? // // 根據(jù)修改時間來判斷是否緩存? ? ? ? //if(ifModifiedSince){? ? ? ? //if(ifModifiedSince !== lastModified){? ? ? ? //? ? ? ? // 上一次修改的時間和最新修改的時間不一樣? ? ? ? //returnfalse//? 不走緩存? ? ? ? //? ? }? ? ? ? // }? ? ? ? // 壓縮和緩存是后端程序干的if(ifModifiedSince &&ifNoneMatch){if(ifNoneMatch !== Etag &&ifModifiedSince !== lastModified){returnfalse}? ? ? ? }else{returnfalse}returntrue} sendFile(filePath, req, res,statObj) {? ? ? ? res.setHeader("Cache-Control","no-cache");letcache = this.cache(filePath, req, res,statObj)if(cache){? ? ? ? ? ? res.statusCode = 304;returnres.end()? ? ? ? }letflag = this.gzip(filePath, req, res,statObj)lettype= mime.getType(filePath) ||"text/plain"res.setHeader("Content-Type",type+"; charset=utf8")if(!flag){? ? ? ? ? ? fs.createReadStream(filePath).pipe(res)? ? ? ? }else{? ? ? ? ? ? fs.createReadStream(filePath).pipe(flag).pipe(res)? ? ? ? }? ? }復(fù)制代碼

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鼻忠,隨后出現(xiàn)的幾起案子涵但,更是在濱河造成了極大的恐慌,老刑警劉巖帖蔓,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件矮瘟,死亡現(xiàn)場離奇詭異,居然都是意外死亡塑娇,警方通過查閱死者的電腦和手機(jī)澈侠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來埋酬,“玉大人哨啃,你說我怎么就攤上這事⌒赐祝” “怎么了棘催?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長耳标。 經(jīng)常有香客問我,道長邑跪,這世上最難降的妖魔是什么次坡? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮画畅,結(jié)果婚禮上砸琅,老公的妹妹穿的比我還像新娘。我一直安慰自己轴踱,他們只是感情好症脂,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著淫僻,像睡著了一般诱篷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上雳灵,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天棕所,我揣著相機(jī)與錄音,去河邊找鬼悯辙。 笑死琳省,一個胖子當(dāng)著我的面吹牛迎吵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播针贬,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼击费,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了桦他?” 一聲冷哼從身側(cè)響起蔫巩,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瞬铸,沒想到半個月后批幌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嗓节,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年荧缘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拦宣。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡截粗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸵隧,到底是詐尸還是另有隱情绸罗,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布豆瘫,位于F島的核電站珊蟀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏外驱。R本人自食惡果不足惜育灸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望昵宇。 院中可真熱鬧磅崭,春花似錦、人聲如沸瓦哎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒋譬。三九已至割岛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間犯助,已是汗流浹背蜂桶。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留也切,地道東北人扑媚。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓腰湾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親疆股。 傳聞我的和親對象是個殘疾皇子费坊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

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