Gzip是GNUzip的缩写,最早用于UNIX系统的文件压缩。HTTP协议上的Gzip编码是一种用来改进Web应用程序性能的技术,Web服务器和客户端(浏览器)必须共同支持Gzip。目前主流浏览器:Chrome、Firefox等都支持该协议,常见的服务器:Apache、Nginx、IIS同样支持Gzip。

Gzip的压缩比率在3-10倍左右(纯文本),可以大大节省服务器的网络带宽。在实际应用中,并不是对所有文件进行压缩,通常只压缩静态文件(js\css\html)。JPEG这类文件用Gzip压缩的不够好,而且压缩也是耗费CPU资源的。

那么Gzip是如何进行压缩的呢?简单来说,Gzip压缩是在一个文本文件中找出类似的字符串,并临时替换他们,使整个文件变小。这种形式的压缩对Web来说非常合适,因为HTML和CSS文件通常包含大量的重复字符串,例如空格、标签等。

一、HTTP内容编码和HTTP压缩的区别

HTTP压缩在HTTP协议中,其实是内容编码的一种。在HTTP协议中,可以对内容(也就是body部分)进行编码,可以采用Gzip编码,从而达到压缩的目的。也可以使用其他的编码把内容搅乱或加密,以此来防止未授权的第三方看到文档的内容。
所以HTTP压缩,其实就是HTTP内容编码的一种。

二、内容编码类型

HTTP定义了一些标准的内容编码类型,并允许用扩展的形式添加更多编码。Response Header中包含的Content-Encoding属性,就是用这些标准化的代号来说明编码时使用的算法。

Content-Encoding释义
gzip实体采用GNUzip编码
compress实体采用Unix的文件压缩程序
deflate实体采用zlib的格式压缩
identity表明没有对实体进行编码。当没有Content-Encoding 时,就默认是这种情况

gzip、compress、deflate编码都是无损压缩算法,用于减少传输报文的大小,不会导致信息损失。gzip通常效率最高,使用范围最广。

那么客户端和服务器之间是如何进行通信来支持Gzip的呢?

三、HTTP压缩的过程

在这里插入图片描述
(1)浏览器请求资源,并在Request Header中设置属性Accept-Encoding:gzip,deflate, sdch;表明浏览器支持这三种压缩。

  • deflate与gzip使用的压缩算法几乎相同。
  • sdch是Shared Dictionary Compression over HTTP的缩写,即通过字典压缩算法对各个页面中相同的内容进行压缩,减少相同的内容的传输。sdch是Google推出的,目前只在Google Chrome, Chromium 和Android中支持。

(2)服务器收到浏览器发送的请求之后,判断浏览器是否支持Gzip,如果支持Gzip,则向浏览器传送压缩过的内容,如果不支持,则向浏览器发送未经压缩的内容。一般情况下,浏览器和服务器都支持Gzip。Response Header返回包含Content-Encoding: gzip;的响应头。

(3)浏览器接收到服务器的响应之后,判断内容是否被压缩,如果被压缩则进行解压,然后显示内容。

在这里插入图片描述

在线检测工具可以进行检测Gzip压缩效率。如下图:
在这里插入图片描述

很明显可以看出,通过使用Gzip,静态文件被压缩了68.063%,极大地节省了服务器的网络带宽。

四、Gzip压缩的两种方式

  1. 服务端压缩:浏览器请求js、css等文件的时候,服务器对js、css等文件进行gzip压缩后传输给浏览器;
  2. 前端压缩:打包的时候通过webpack生成对应的.gz文件,浏览器请求js、css等文件的时候,服务器返回对应jxx.js.jz、xx.css.gz文件;

1、nginx服务器动态进行gzip压缩
每次请求js、css等文件时,服务器会进行实时压缩;另一方面,压缩一定要和静态文件缓存相结合,缓存压缩后的版本,否则每次都压缩,高负载下服务器肯定吃不住;还需要做一下压力测试。
nginx配置参考:nginx中如何设置gzip(总结)

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip  on;//# 开启gzip
    gzip_buffers 4 16k;//# 设置缓冲区大小
    gzip_comp_level 6;//#压缩级别官网建议是6,压缩级别(级别越高,压的越小,越浪费CPU计算资源)
    gzip_min_length 100;//允许被压缩的页面最小字节数
    gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php;//#压缩的类型
    gzip_disable "MSIE [1-6]\."; //#配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
    gzip_vary on;//是否传输gzip标识
    gzip_http_version 1.1;//# 使用 GZIP 压缩的最小 HTTP 版本

    server {
        listen       8462;
        server_name  localhost;

        location / {
            root   dist;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

其他配置项:

gzip_proxied //# 设置请求者代理服务器,该如何缓存内容
gzip_disable //#正则匹配UA 什么样的Uri不进行gzip

2、webpack打包生成gz文件
(1)安装插件compression-webpack-plugin(选择合适的版本,可以在npm上查看所有版本)

npm install compression-webpack-plugin --save-dev

(2)vue-cli3:在vue.config.js 文件中配置 compression-webpack-plugin

const CompressionWebpackPlugin = require('compression-webpack-plugin');//引入插件
const productionGzipExtensions = ['js', 'css']; //压缩的文件类型

module.exports ={
  configureWebpack: (config) => {
    if (process.env.NODE_ENV === 'production') {
      // 仅在生产环境下启用该配置
      return {
        plugins: [
          new CompressionWebpackPlugin({
            //[file] 会被替换成原始资源。[path] 会被替换成原始资源的路径, [query] 会被替换成查询字符串。默认值是 "[path].gz[query]"。
            filename: '[path].gz[query]',
            algorithm: 'gzip',
            test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
            threshold: 1024, // 只有大小大于该值的资源会被处理,当前配置为对于超过1k的数据进行处理,不足1k的可能会越压缩越大
            minRatio: 0.99, // 只有压缩率小于这个值的资源才会被处理,默认值是 0.8。
            deleteOriginalAssets: false // 删除原文件
          })
        ]
      }
    }
  },
}

这里对js、css、html文件进行了压缩处理,并没有对图片压缩,因为图片压缩并不能实际减小文件大小,反而会导致打包后生成很多同大小的gz文件,得不偿失。

(3)配置nginx服务器,返回.gz类型文件

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip_static on;//静态加载本地的gz文件,需要在nginx上安装http_gzip_static_module模块(主要作用是,对于需要压缩的文件,直接读取已经压缩好的文件,即文件名为加.gz的文件,而不是动态压缩消耗性能)
    server {
        listen       8462;
        server_name  localhost;
        location / {
            root   dist;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

压缩后的效果:
在这里插入图片描述

nginx配置了静态gz加载后,服务器返回的也是gz文件,这样请求文件小,就不会导致请求卡线程。因为保留了源文件,当删除gz文件后,浏览器会自动去请求原始文件,不会导致界面出现任何问题。

3、两种方案优缺点
(1)使用nginx动态生成gzip,缺点是耗性能,需要实时压缩,但是vue打包后的文件体积小;
(2)webpack打包生成静态gz文件,然后直接使用静态的gz文件,这种方法的缺点是打包后文件体积大,但是不耗费服务器性能;

如果要实现:有gz文件的时候使用静态资源,不存在gz文件的时候进行在线压缩而不是加载源文件,需要把两种配置都写上,如下:

gzip on;
gzip_static on;
gzip_comp_level 2;
gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript; 

gzip_static的优先级高,会先加载静态gz文件,当同目录下不存在此文件的时候,会执行在线压缩命令。
响应头的Content-Edcoding:gzip表示gzip压缩已经生效,而Etag中只有简单字符表示静态资源加载,而前面带 W/ 表示启动了在线压缩。

在这里插入图片描述

补充:
静态资源服务器全部使用的Nginx,且都开启了gzip压缩。内部测试是完全正常的,然而一到外网,居然没有做gzip?
原因:做负载均衡的机器上面没开gzip,在应用服务器前,公司还有一层Nginx的集群作为七层负责均衡,在这一层上,是没有开启gzip的。还需要设置gzip_http_version为1.0:nginx和后端的upstream server之间默认是用HTTP/1.0协议通信的。
在应用服务器前,公司还有一层Nginx的集群作为七层负责均衡,在这一层上,是没有开启gzip的。如果我们使用了proxy_pass进行反向代理,那么nginx和后端的upstream server之间默认是用HTTP/1.0协议通信的。
如果我们的Cache Server也是nginx,而前端的nginx没有开启gzip。同时,我们后端的nginx上没有设置gzip_http_version为1.0,那么Cache的url将不会进行gzip压缩。

参考文章:
vue-cli3构建的项目使用compression-webpack-plugin 进行Gzip压缩

Logo

前往低代码交流专区

更多推荐