项目打包结束后,在终端上会展示三列(File、Size、Gzipped),Gzipped压缩后的文件大小显然比Size小,而我们打包后的文件都是没有压缩的,如果项目文件很大就会影响到首页白屏时间过长,因此研究了下
Gzip
。
一、Gzip压缩原理
1.1 原理
Gzip 压缩背后的原理,是在一个文本文件中找出一些重复出现的字符串、临时替换它们,从而使整个文件变小。根据这个原理,文件中代码的重复率越高,那么压缩的效率就越高,使用 Gzip的收益也就越大。反之亦然。
1.1.1 HTTP压缩原理
HTTP 压缩是一种内置到网页服务器和网页客户端中以改进传输速度和带宽利用率的方式。在使用 HTTP 压缩的情况下,HTTP 数据在从服务器发送前就已压缩:兼容的浏览器将在下载所需的格式前宣告支持何种方法给服务器;不支持压缩方法的浏览器将下载未经压缩的数据。最常见的压缩方案包括 Gzip
和 Deflate
。
1.1.2 webpack 的 Gzip 和服务端的Gzip
参考 webpack优化性能/首屏加载时间
一般来说,Gzip 压缩是服务器的活儿:服务器了解到我们这边有一个 Gzip 压缩的需求,它会启动自己的 CPU 去为我们完成这个任务。而压缩文件这个过程本身是需要耗费时间的,大家可以理解为我们以服务器压缩的时间开销和 CPU 开销(以及浏览器解析压缩文件的开销)为代价,省下了一些传输过程中的时间开销。
既然存在着这样的交换,那么就要求我们学会权衡。服务器的 CPU 性能不是无限的,如果存在大量的压缩需求,服务器也扛不住的。服务器一旦因此慢下来了,用户还是要等。Webpack 中 Gzip 压缩操作的存在,事实上就是为了在构建过程中去做一部分服务器的工作,为服务器分压。
因此,这两个地方的 Gzip 压缩,谁也不能替代谁。它们必须和平共处,好好合作。作为开发者,我们也应该结合业务压力的实际强度情况,去做好这其中的权衡。
1.2 实现
不是每个浏览器都支持Gzip
的,如何知道客户端是否支持Gzip呢,请求头中有个Accept-Encoding:gzip
来标识对压缩的支持。客户端http请求头声明浏览器支持的压缩方式,服务端配置启用压缩,压缩的文件类型,压缩方式。当客户端请求到服务端的时候,服务器解析请求头,如果客户端支持Gzip压缩,响应时对请求的资源进行压缩并返回给客户端,浏览器按照自己的方式解析,在http响应头,我们可以看到content-encoding:gzip
,这是指服务端使用了Gzip的压缩方式(图1-1)。
1.3 如何看是否使用了Gzip压缩的文件
开发者工具 -> network -> content-encoding:gzip
1.3 Gzip优缺点
优点
减少文件大小。Gzip压缩比率在3到10倍左右,可以大大节省服务器的网络带宽。而在实际应用中,并不是对所有文件进行压缩,通常只是压缩静态文件。 减少文件大小有两个明显的好处,①是可以减少存储空间,②是通过网络传输文件时,可以减少传输的时间。 对于带宽较低的服务器是一种利好,开启后可以加快我们网站的打开速度,原理是经过服务器压缩,客户端浏览器快速解压的原理,可以大大减少网站流量。
缺点
- 需要nginx、服务端的支持,占用了一些服务器和客户端的CPU;
- 操作失误,会造成网站无法访问;
- 蜘蛛无法进行爬行,造成收录不佳;
- 谷歌可以完美的支持Gzip压缩,百度支持的并不太好;
二、启用Gzip
2.1 vue.config.js
安装npm i compression-webpack-plugin@5.0.1
如果安装的时候报RROR TypeError:Cannot read property ‘tapPromise‘ of undefined
可能是compression-webpack-plugin
版本问题(采用5.0.1版本)
// webpack启用Gzip压缩
const CompressionPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = ['js', 'css'];
const isPRD = process.env.NODE_ENV === 'production';
module.exports = {
configureWebpack: {
plugins: isPRD ? [
// 使用Gzip压缩文件 - https://segmentfault.com/a/1190000012571492
// 报错:"TypeError: Cannot read property 'tapPromise' of undefined"是compression-webpack-plugin版本问题5.0.1
new CompressionPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
threshold: 10240,
minRatio: 0.8
})
] : []
},
}
2.2 服务端
这里使用的是node,所以以node配置为例
安装compression npm i compression
// 服务端开启Gzip支持
var compression = require('compression');
//尽量在其他中间件前使用compression
app.use(compression());
2.3 nginx配置
http {
# nginx开启Gzip:若没有找到.gz,会动态压缩,因此建议前端打包成.gz文件
# 是否启用Gzip(on为启用,off为关闭)
gzip on;
# 设置允许压缩的页面最小字节数,页面字节数从header头中的Content-Length中进行获取。默认值是0,不管页面多大都压缩。建议设置成大于1k的字节数,小于1k可能会越压越大。
gzip_min_length 1k;
# 获取多少内存用于缓存压缩结果,‘4 16k’表示以16k*4为单位获得
gzip_buffers 4 16k;
# Gzip压缩比(1~9),越小压缩效果越差,但是越大处理越慢,所以一般取中间值;
gzip_comp_level 5;
# 对特定的MIME类型生效,其中'text/html'被系统强制启用(少啥类型就添加啥)
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
# 识别http协议的版本,早起浏览器可能不支持Gzip自解压,用户会看到乱码
gzip_http_version 1.1;
# 启用应答头"Vary: Accept-Encoding"
gzip_vary on;
# ie6以下禁用Gzip
gzip_disable "MSIE [1-6]\.";
}
三、注意点
- 低版本浏览器兼容问题,如果你的站点必须在window95的网景1.0浏览器上,你可能不想要压缩文件。Apache mod_deflate设置了一些忽略规则来专门为旧浏览器。
- 建议只压缩HTML,CSS,JAVARSCRIPT;大多数的图片,音乐和视频都已经压缩过了,不要浪费时间来压缩他们了。
- CPU负载:在传输过程中压缩文件耗费CPU但是节省带宽(用空间换时间)。