gzip简介
HTTP协议上的gzip编码是一种用来改进web应用程序性能的技术,web服务器和客户端(浏览器)必须共同支持gzip。目前主流的浏览器都支持该协议。
简单来说,gzip是一种压缩技术。经过gzip压缩后,文件大小为原来的30%甚至更小,这样,用户浏览页面的时候速度会快得多。
那么客户端和服务器之间是如何通信来支持gzip的呢?通过下图我们可以很清晰的了解。
客户端http请求头Accept-Encoding
声明浏览器支持的压缩方式,服务端配置启用压缩,压缩的文件类型,压缩方式。当客户端请求到服务端的时候,服务器解析请求头,如果客户端支持gzip压缩,响应时对请求的资源进行处理并返回给客户端,浏览器按照自己的方式解析,在http响应头,我们可以看到content-encoding:gzip
,这是指服务端使用了gzip的压缩方式,返回的是gzip文件。
服务器返回gzip文件的处理方式可以有两种:
- 前端打包的时候生成了对应的.gz文件,则浏览器请求xx.js时,服务器返回对应的xxx.js.gz文件
- 否则,浏览器请求xx.js时,服务器对xx.js进行gzip压缩后传输给浏览器
通常情况,前端会在打包时生成对应文件的.gz文件,缓解服务器端压缩并缓存gzip文件时,对处理器和内存造成的压力。
安装前端压缩插件
安装compression-webpack-plugin包
npm i -D compression-webpack-plugin
由于脚手架版本兼容问题,直接安装最新版可能会导致报错
TypeError: Cannot read property ‘tapPromise’ of undefined
我这里vue cli是4.4.6版本,安装的是6.1.1版本
npm i -D compression-webpack-plugin@6.1.1
修改vue.config.js文件
在vue.config.js文件中添加以下代码,和gizp压缩无关的代码这里已去除
const isProd = process.env.NODE_ENV === 'production';
const vueConfig = {
configureWebpack: {
// webpack plugins
plugins: [
......
]
}
}
if(isProd) {
// production模式下,plugins中添加文件压缩处理器
const CompressionWebpackPlugin = require('compression-webpack-plugin');
vueConfig.configureWebpack.plugins.push(new CompressionWebpackPlugin({
test: /.js|.css/, // 对匹配的文件类型进行压缩
}))
}
module.exports = vueConfig;
服务器端如何启用gzip
前面说过了,启用gzip需要客户端和服务端的支持,如果客户端支持gzip的解析,那么只要服务端能够返回gzip的文件就可以启用gzip了,现在来说一下几种不同的环境下的服务端如何配置。
nginx启用gzip
gzip使用环境:http,server,location,if(x),一般把它定义在nginx.conf的http{......}之间
修改nginx配置,在server里添加以下代码,与listen同级
gzip on; # 开启Gzip
gzip_static on; # 开启静态文件压缩
gzip_min_length 1k; # 不压缩临界值,大于1K的才压缩
gzip_buffers 4 16k;
gzip_comp_level 5;
gzip_types application/javascript application/x-javascript application/xml application/xml+rss application/x-httpd-php text/plain text/javascript text/css image/jpeg image/gif image/png; # 进行压缩的文件类型
gzip_http_version 1.1;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6].";
- gzip on
on为启用,off为关闭 - gzip_min_length 1k
设置允许压缩的页面最小字节数,页面字节数从header头中的Content-Length中进行获取。默认值是0,不管页面多大都压缩。建议设置成大于1k的字节数,小于1k可能会越压越大。 - gzip_buffers 4 16k
获取多少内存用于缓存压缩结果,‘4 16k’表示以16k*4为单位获得 - gzip_comp_level 5
gzip压缩比(1~9),越小压缩效果越差,但是越大处理越慢,所以一般取中间值; - gzip_types application/javascript application/x-javascript application/xml application/xml+rss application/x-httpd-php text/plain text/javascript text/css image/jpeg image/gif image/png
对特定的MIME类型生效,其中'text/html’被系统强制启用 - gzip_http_version 1.1
识别http协议的版本,早期浏览器可能不支持gzip自解压,用户会看到乱码 - gzip_vary on
启用应答头"Vary: Accept-Encoding" - gzip_proxied off
nginx做为反向代理时启用off(关闭所有代理结果的数据的压缩),
expired(启用压缩,如果header头中包括"Expires"头信息),
no-cache(启用压缩,header头中包含"Cache-Control:no-cache"),
no-store(启用压缩,header头中包含"Cache-Control:no-store"),
private(启用压缩,header头中包含"Cache-Control:private"),
no_last_modefied(启用压缩,header头中不包含"Last-Modified"),
no_etag(启用压缩,如果header头中不包含"Etag"头信息),
auth(启用压缩,如果header头中包含"Authorization"头信息) - gzip_disable "MSIE [1-6]."
(IE5.5和IE6 SP1使用msie6参数来禁止gzip压缩 )指定哪些不需要gzip压缩的浏览器(将和User-Agents进行匹配),依赖于PCRE库
tomcat 启用gzip
找到tomcat的server.xml文件,找到其中Connector节点然后进行配置修改,具体配置如下
<Connectorport="80"protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" maxPostSize="0" useBodyEncodingForURI="true" compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata" compressableMimeType="text/html,text/xml,application/javascript,text/css,text/plain,image/jpeg,application/json"/>
参数说明:
- compression="on" 打开压缩功能
- compressionMinSize="2048" 启用压缩的输出内容大小,当被压缩对象的大小>=该值时才会被压缩,这里面默认为2KB
- noCompressionUserAgents="gozilla, traviata" 对于以下的浏览器,不启用压缩
- compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" 压缩类型
注意: tomcat7以后,js文件的mimetype类型变为了application/javascript,而在tomcat7以下则为text/javascript;具体的tomcat7定义的类型可以在:conf/web.xml文件中找到。
可以在web.xml下搜索,如我搜索javascript会找到如下代码
<mime-mapping>
<extension>js</extension>
<mime-type>application/javascript</mime-type>
</mime-mapping>
切记上面的类型不能配置错了,如果配置错了压缩是不会起作用的。
node端启用gzip
node端很简单,只要加上compress模块即可,代码如下
var compression = require('compression')
var app = express();
//尽量在其他中间件前使用compression
app.use(compression());
这是基本用法,如果还要对请求进行过滤的话,还要加上
app.use(compression({filter: shouldCompress}))
function shouldCompress (req, res) {
if (req.headers['x-no-compression']) {
// 这里就过滤掉了请求头包含'x-no-compression'
return false
}
return compression.filter(req, res)
}
更多用法请移步compression文档
如果用的是koa,用法和上面的差不多
const compress = require('koa-compress');
const app = module.exports = new Koa();
app.use(compress());
因为node读取的是生成目录中的文件,所以要先用webpack等其他工具进行压缩成gzip。
验证处理结果
运行打包命令 npm run build,可以看到生成的dist文件夹中的js和css文件多出了同名.gz文件,这里以js文件举例。
打包后上传服务器查看效果,可以发现浏览器上下载的是gzip压缩后的文件。
通过Network可看到 Request Headers 和 Response Headers 里都带有gzip标记
注: 开发环境下,无法查看压缩效果