## HTTP系列之Accept-Encoding和Content-Encoding

wingtao發表於2019-04-08

前端的效能優化是一個永不停歇的路程,優化的方式也不一而足,今天重點不在於介紹效能優化,而是介紹效能優化的其中一種方式,通過壓縮來節省http請求的流量,實現過程中依賴http中header部分的兩個欄位,Accept-Encoding和Content-EnCoding(分別來自request的header和response的header)。

前兩天排查一個問題是注意到專案裡ssr時返回的頁面竟然沒有壓縮,頁面體積大小高達182k,於是著手優化這部分。首先我們先了解下Accept-Encoding和Content-Encoding的作用。

含義與作用

為什麼首先要講這兩個欄位的含義呢?因為當你開啟一個頁面時,請求到了服務端,如果請求上沒有這種編碼的標識的話,服務端是不知道該不該壓縮?使用哪種方式壓縮的?所以request請求header裡的Accept-Encoding就是用來告訴服務端客戶端是支援哪些編碼方式的,一般的值有gzip/compress/deflate/br等,可以多個,中間用逗號隔開。如:

Accept-Encoding: gzip, deflate, br
複製程式碼

當服務端接收到請求,並且從header裡拿到編碼標識時,就可以選擇其中一種方式來進行編碼壓縮,然後返給客戶端,但是如果response的header裡沒有編碼標識的話,客戶端就不知道服務端是用的哪種方式壓縮的,所以需要Content-Encoding來標識服務端壓縮時所用的壓縮方式。

綜上,Accept-Encoding用來標識客戶端能夠理解的內容編碼方式。 Content-Encoding用來標識主體進行了何種方式的內容編碼轉換。

node中的使用

專案中使用的node實現的ssr,因此重要討論下在node中實現壓縮來完成效能的優化。實現程式碼簡化如下:

const http = require('http');
const zlib = require('zlib');

const server = http.createServer(function(req,res){
	//...其他邏輯
	const acceptEncoding = req.headers['accpent-encoding'];
	if(!!acceptEncoding.match(/\bgzip\b/)){
		zlib.gzip(body,function(err,data){
			if(err){
				//...錯誤處理邏輯
			}
			res.setHeader('content-encoding','gzip');
			res.setHeader('content-length',body.length);
			res.end(body);
		})
	}
	// ...非gzip處理
});
複製程式碼

node中壓縮是通過zlib來實現的,首先判斷accept-Encoding裡是否有gzip,有的話通過zlib壓縮,並在response的header中標識。很簡單吧!

結語

之前看http總是感覺很枯燥,看不下去,但通過與專案中的實踐相結合還是蠻有意思的,比如這次雖然是一個比較小的優化點,但是還是有點成就感的。

如果本文對你有些許幫助,就請你點個贊鼓勵下!

相關文章