前端性能优化一直是一个值得讨论的话题,而节省每次HTTP请求的流量,则是优化的一个重要的点,好比javascript文件、图片、样式表等进行压缩传输,不只使访问速度更快,也能够有效的节省站点的流量。javascript
HTTP的请求中带有一个头Content-Encoding
来处理压缩。前端
常见的压缩模式:java
GZIP最先由Jean-loup Gailly和Mark Adler建立,用于UNⅨ系统的文件压缩。咱们在Linux中常常会用到后缀为.gz的文件,它们就是GZIP格式的。现今已经成为Internet 上使用很是广泛的一种数据压缩格式,或者说一种文件格式。node
DEFLATE是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。 它最初是由Phil Katz为他的PKZIP归档工具第二版所定义的,后来定义在RFC 1951规范中。算法
node.js中已经为咱们提供了压缩的功能,它的核心功能在zlib包里。浏览器
zlib模块提供经过 Gzip 和 Deflate/Inflate 实现的压缩功能。性能优化
const zlib = require('zlib');
const fs = require('fs');
const path = require('path');
let file = path.join(__dirname, './1.txt');
zip(file);
function zip(file) {
let gzip = zlib.createGzip(); //gzip是一个转换流
fs.createReadStream(file).pipe(gzip).pipe(fs.createWriteStream(file + '.gz'));
}
复制代码
能够看到用法很是简单,使用createGzip能够建立一个gzip压缩流,它是一个Transform转换流。首先使用待压缩的目标文件建立一个可读流,将它pipe到gzip压缩流中,再pipe到一个可写流中,便可完成压缩。运行这段代码能够看到在模块目录下已经多了一个1.txt.gz的压缩包。服务器
unzip(path.join(__dirname, './1.txt.gz'));
function unzip(file) {
let gunzip = zlib.createGunzip(file);
fs.createReadStream(file).pipe(gunzip).pipe(fs.createWriteStream(path.basename(file, '.gz')));
}
复制代码
解压缩一样如此,使用解压缩流便可。前端性能
了解了压缩流的使用,怎么样才能配合http来优化用户的请求呢?工具
http有一个字段,它描述了浏览器支持哪一种压缩格式:
Accept-Encoding: gzip, deflate, br
复制代码
响应头
Content-Encoding: gzip
复制代码
处理流程:
Accept-Encoding
都支持哪些压缩格式Content-Encoding
实例代码:
const http = require('http');
const url = require('url');
const path = require('path');
const fs = require('fs');
const zlib = require('zlib');
let server = http.createServer((req, res) => {
let {pathname} = url.parse(req.url, true);
if (pathname === '/') {
res.end('请访问一个服务器上的文件 如http://localhost:3000/1.txt');
}
let file = path.join(__dirname, pathname);
fs.stat(file, (err, stat) => {
if (err) {
res.end('访问的文件不存在');
} else {
let acceptEncoding = req.headers['accept-encoding']; //取得浏览器的accept-encoding头,询问支持哪一种压缩
if (acceptEncoding.match(/\bgzip\b/)) { //浏览器支持gzip格式
res.setHeader('Content-Encoding', 'gzip'); //告知浏览器发送的数据是gzip压缩格式
let gzip = zlib.createGzip();
fs.createReadStream(file).pipe(gzip).pipe(res); //压缩后输出
} else if (acceptEncoding.match(/\bdeflate\b/)) { //浏览器支持deflate格式
let deflate = zlib.createDeflate();
res.setHeader('Content-Encoding','deflate');
fs.createReadStream(file).pipe(deflate).pipe(res); 压缩后输出
} else {
fs.createReadStream(file).pipe(res);
}
}
});
});
server.listen(3000, () => {
console.log('服务器已启动在3000端口...')
});
复制代码
重要代码说明:
let acceptEncoding = req.headers['accept-encoding'];
复制代码
取得浏览器的请求头,查看支持哪些压缩格式,由于某些老旧浏览器是不支持压缩的,所以要针对不一样的压缩格式分别处理。
if (acceptEncoding.match(/\bgzip\b/)) {
复制代码
使用正则来进行判断,看看是否支持gzip压缩
res.setHeader('Content-Encoding', 'gzip'); //告知浏览器发送的数据是gzip压缩格式
复制代码
使用setHeader来设置响应头,告知浏览器此数据是经gzip压缩的,这样浏览器才会正确处理,不然浏览器并不识别gzip数据。
deflate格式的逻辑彻底同样,这样就能够作到http压缩以节省流量的目的。