初识gzip
在使用webpack打包前端文件时,在一些文章中无心中看到过使用gzip压缩技术,达到优化打包文件大小的效果。简单配置操做以后,发现压缩后的gzip文件,压缩效果很好,至少可压缩一半大小!惊讶之余同时也有不少疑问,好比:css
- gzip压缩技术,如何用到已有的web项目中呢?
- 后来又在其它地方看到nginx也能够作gzip,那么webpack和nginx的gzip有什么关系吗?
- 这么好的工具,为何之前所经历的项目中并无接触到呢?
- 是否是这个技术有什么坑?
带着不少问题,开始查资料,作demo,一点一点了解它,慢慢的揭开它的真面目。
gzip和文件压缩
Gzip是若干种文件压缩程序的简称,“GNU计划” 的实现,使用c语言实现。gzip的基础是DEFLATE,DEFLATE是LZ77与哈夫曼编码的一个组合体。初始版本于1992年10月31日,25年前发布。 可见,gzip本来是在Unix-like操做系统上用来作数据压缩的一种工具。html
gzip和http协议
HTTP压缩是一种内置到网页服务器和网页客户端中以改进传输速度和带宽利用率的方式,最多见的压缩方案包括gzip和Deflate。具体压缩算法还有其它类型,这里不作展开。可见gzip只是http压缩方案中的其中一种,其完整流程须要客户端和服务端同时支持。
那么服务端和客户端分别如何支持gzip的呢?前端
客户端vue
- 支持http压缩的客户端在发送请求的header里配置 Accept-Encoding字段,用于说明本身可以理解的内容编码方式。在接收到返回的数据后去检查服务端响应头,而后根据对应的格式去作相应的解码,目前主流的浏览器,Chrome,firefox,IE等都支持该协议。
- 不支持http压缩的客户端在发送请求的header里配置不会添加Accept-Encoding字段。
服务端
服务端接收到客户端请求头Accept-Encoding字段后,端会选择其中一种压缩方案进行压缩,使用并在响应报文首部 Content-Encoding 中表示消息主体进行了何种方式的内容编码转换,告知客户端应该怎样解码才能获取在 Content-Type 中标示的媒体类型内容。常见的服务器如Apache,Nginx,IIS都支持gzip。java
HTTP协议gzip压缩的过程
- 客户端发送Http request 给Web服务器, 兼容压缩方案的浏览器会在http请求头中带上有Accept-Encoding: gzip。(告诉服务器, 客户端支持gzip压缩)
- 服务器对须要返回的文件进行Gzip压缩,或者查找静态资源是否存在已经压缩好的gzip压缩文件。(服务端想办法生成或找到原始文件对应的gzip压缩文件)
- 服务端将gzip文件发送给客户端,而且设置相应header中除了包含有Content-Type,Content-Length等字段,还须要添加Content-Encoding:gzip用于说明压缩文件的编码方式。(服务端返回gzip文件并告诉客户端压缩方式为gzip)
- 客户端接到Response后,根据Content-Encoding:gzip来对Response 进行解码。 获取到原始response后, 而后显示出网页。(客户端对gzip文件解码)
谁来作压缩?
服务端
- 若是服务是部署在nginx上,可使用nginx 开启 gZip 配置便可完成文件压缩。
- 若是服务是独立部署,没有部署在nginx等服务器上。好比常见的用于进行接口鉴权和文件转发的node服务,须要在服务端实现gzip功能。具体如何实现,本人目前尚未实践,我的猜测应该是寻找可用当前服务器语言对应的现成工具实现,若是没有现成工具,则须要服务端自行完成。
客户端
如今前端流行 spa 应用, 用 react, vue 之类的框架,通常配备 webpack 做为打包工具,webpack有个插件 compression-webpack-plugin 能够对打包文件进行 gZip 等压缩并生成对应的压缩文件。node
我的2点想法
- 若是服务端作压缩,尽可能使用ngnix作
服务端实现gzip压缩的过程是相似的。 服务端收到客户端请求后,先会找到对应的文件, 而后对文件进行压缩,并配置好Content-Encoding 信息,返回压缩后的内容,
- 若是应用没有上游代理层nginx等,好比服务端就一层 node 就能够直接用本身自己的压缩插件对文件进行压缩。
- 若是上游配有 nginx 转发处理层,最好交给 nginx 来处理这些,nginx自己就自带gzip压缩功能,毕竟专业的事交给专业的工具作更为放心。
- 提早预压缩
在服务端作gzip压缩,压缩发送在请求过程当中,须要耗费更多的CPU和时间,固然相似nginx的压缩可能不必定每次都须要压缩(待调研),但至少第一次压缩是须要的。
预压缩就是提早把静态文件进行gzip压缩,当请求来的时候,直接读走。这样服务器就没了压缩消耗,而浏览器的解压缩性能相比网络IO,影响不大。
有一种预压缩方案能够是使用客户端webpack作gzip压缩,而后开启nginx的gzip_static选项(若是服务端不是nginx,实现方案待调研)
因为只有在上线项目时才打包构建一次,即便在构建时使用最高级的压缩方式压缩,多耗费一些打包时间根本没任何损耗,这样服务器也不用再去压缩文件,只须要找到相应已经压缩过的文件直接返回就能够了。
总结
能开启 gZip 确定是要开启的,具体使用在请求时候实时压缩仍是在构建时候去生成压缩文件,就要看本身具体业务状况。python
大厂在用吗?
了解大厂们是否在使用,是为了知道做为小白的我可否放心使用这项技术的参考之一。
在我写这篇文章时,默默查看了下BAT首页,京东,考拉...都用了gzip压缩,这说明这个技术目前已经普及了。react
以淘宝首页为例查看请求和相应header便可知道是否使用gzip压缩。 webpack
了解了关于gzip的一些基础问题以后,下面主要演示一些demo小例子,介绍如何在web中应用这项技术。nginx
nginx作压缩应用gzip
若是服务器是部署在nginx,则能够经过修改nginx的配置文件实如今nginx中实现gzip压缩,步骤以下:
1.准备好待测试的静态页面
写一个简单的静态页面,引入vue.js和element-ui.js(用来查看是否有gzip效果)
打开nginx的配置文件,将nginx的root目录指向这个静态页面所在的目录。
2.启动gzip配置
在server下打开gzip开关
3.重启nginx服务
配置好以后,重载nginx配置便可(若是重载不成功,则重启)
这里的命令是mac系统上的nginx重启命令。
sudo brew services reload nginx
sudo brew services restart nginx
效果:文件大小对比
对比没有开启gzip和开启了gzip的文件大小。 能够看到压缩后的html,js,css文件比原始文件小不少,可见这个压缩效果至关可观的。
webpack作压缩应用gzip
在webpack中主要是经过插件compression-webpack-plugin实现本地打包时的gzip压缩,具体步骤以下:
1.准备好待测试的使用webpack打包的工程
略,读者自行实现。
2.安装配置compression-webpack-plugin
安装插件
npm install compression-webpack-plugin --save-dev
3.修改webpack配置
在webpack配置文件中添加下面几行配置:
const CompressionPlugin = require('compression-webpack-plugin');
...
plugins: [new CompressionPlugin() ]
4.执行本地打包
- 没有使用compression-webpack-plugin的打包结果: 只有2个文件,build.js是958878
- 使用了compression-webpack-plugin的打包结果:生成了4个文件,build.js是958878,build.js.gz是231189
5. 服务端配合测试
使用webpack打包时压缩,须要服务端的配合才能生效的。下面以nginx做为服务端为例,测试以下。
首先让nginx的root指向本地打包的index.html页面;
而后关闭或开启nginx的gzip_static配置对比效果;
- 关闭gzip_static,重载nginx配置效果以下
- 开启gzip_static,重载nginx配置
总结和展望
通过上面的分析,再一一回到开头提出的问题
- gzip压缩以后,我怎么用到项目中呢?
答:若是是nginx,须要开启gzip_static配置便可,若是是其它服务器还须要其它服务器自行实现。
- 后来又在其它地方看到nginx也能够作gzip,那么webpack和nginx的gzip有什么关系吗?
答:webpack是一个打包工具,能够打包js,同时经过插件对js文件进行gzip压缩,而后能够将这些文件所有丢给服务端,若是服务部署在nginx则能够作些配置,对.gz文件进行查找,若是找到了则返回.gz给客户端,来代替原始js给客户端,以减小网络传输中的文件大小,若是没找到,也能够配置nginx本身作压缩,而后返回给客户端。所以能够知道nginx能够单独实现gzip,可是webpack须要服务端配合才能实现。
- 这么好的工具,为何之前所经历的项目中并无接触到呢?
答:不知道为何没用...可是了解了这些以后,在之后的项目中,会打算积极的使用gzip压缩的。
- 这个技术有什么坑吗?
答:目前为止我还不知道...
在这个过程当中,又出现了几个新的问题,好比
- 若是是服务不是部署在nginx端,好比部署在node,python,rails,java中的话,如何配合webpack实现gzip呢?
- 若是启用nginx本身的gzip压缩,对于每次请求,nginx每次都是实时计算压缩文件的吗?我的直觉应该不是吧?若是不是,那么使用nginx直接压缩是否是也很方便呢?nginx自身可否实现预压缩呢?
- 除了gzip压缩,其它压缩好比facebook使用的Brotli,是否是压缩效果更好呢?
到此,依然有不少问题须要继续了解...