性能优化实践:快速开启 Gzip 压缩

概念初探

Gzip,全称为 GNU zip,是一种无损压缩文件的算法。其底采用的是 DEFLATE,而 DEFLATE 是 LZ77 与 哈夫曼编码 的一个组合体。

通常来说,“Gzip 压缩”的整体实现流程如下:

  • 浏览器发送请求到服务器,服务器根据请求头中的Accept-Encoding字段判断该浏览器是否支持Gzip压缩。如果不支持,则只响应未经压缩的资源即可;如果支持,则进入后续流程。

    • 方案一:

      服务器端根据接口路径,读取存储在本地的、原始的、未经压缩的静态资源,然后在内存中对其进行“Gzip压缩”,并将压缩后的结果放在响应体中返回给浏览器(响应头中的Content-Encoding字段的值应为gzip)。

      image.png

    • 方案二:

      服务器端根据接口路径,读取存储在本地的、被“Gzip压缩”后的静态资源(即使用 Webpack 配合compression-webpack-plugin对静态资源进行预压缩),并直接将其放在响应体中返回给浏览器(响应头中的Content-Encoding字段的值应为gzip)。

      image.png

  • 浏览器接收到服务器端返回的结果后,会判断响应头中的Content-Encoding字段的值是否为gzip。如果是,则自动将其进行“unGzip”解压,之后在进行其他处理。

经过实践可以发现:开启“Gzip 压缩”后,静态资源的传输效率会得到大幅提升。以我的“全栈个人博客项目”为例,其开启“Gzip压缩”前后各文件的体积大小如下所示:(不难看出,文件的体积越大,压缩效果就越明显)

image.png

但是,服务器的压缩需要时间,浏览器端的解压也需要时间。

在“方案一”中,如果服务器端需要响应的静态资源很多,或同时有大量的用户访问服务器端并请求静态资源,那么服务器端的压力就会剧增,因为每次响应一个静态资源之前,都需要将其读到内存并进行“Gzip”压缩,然后才返回给浏览器端,会产生大量冗余操作。

因此,推荐采用“方案二”,以解决上述问题。即使用 Webpack 配合compression-webpack-plugin插件,在前端工程的打包阶段,对静态资源进行“预压缩”,从而移除服务器端的压缩时间。

开始行动

本次案例所用项目为:全栈个人博客项目

前端工程使用的是Vue 2.6.11@vue/cli 4.5.0,后端工程使用的是NodeJSExpress

前端侧

在工程根目录下,新建vue.config.js文件。先进行如下配置:

module.exports = {
  productionSourceMap: false // 生产环境下关闭源码地图,即不生产对应的map文件,减小打包结果的体积
};

执行npm install compression-webpack-plugin@5.0.0 --save-dev命令,在开发环境下安装compression-webpack-plugin插件。

注意:此处的插件是安装的 5.0.0 版本。因为如果安装最新或较高的版本,在运行npm run build进行打包时,会报如下错误:

TypeError: Cannot read properties of undefined (reading 'tapPromise')

打开vue.config.js文件,配置上述插件以开启“Gzip 压缩”,详细内容如下:

const CompressionPlugin = require("compression-webpack-plugin");
​
module.exports = {
  productionSourceMap: false, 
  configureWebpack: config => {
    // 生产环境下:开启Gzip预压缩
    if(process.env.NODE_ENV === 'production') {
      const gzipExtList = ['html', 'css', 'js']; // 需要Gzip压缩的文件白名单(可自定义)
​
      config.plugins.push(
        new CompressionPlugin({ // 配置Gzip压缩的插件
          filename: "[path].gz[query]", // 默认值
          algorithm: "gzip", // 默认值
          test: new RegExp(`.(${gzipExtList.join('|')})$`),
          threshold: 10240, // 只有体积大于 10KB 的资源会被处理(默认值为 0)
          minRatio: 0.8, // 默认值,只有压缩率优于 0.8 的资源才会被处理(Compressed Size / Original Size)
          deleteOriginalAssets: false // 是否删除原文件(默认值为 false)
        }),
      );
    }
  }
};

后端侧

在本案例所使用的项目中,静态文件资源是存放在使用了express的后端工程的public目录中,并直接交由该Node服务器的express 静态资源中间件进行管理,不直接依赖 Nginx。

因此,直接使用express-static-gzip中间件即可配合前端开启”Gzip 压缩“。该插件的使用方法如下:

const express = require('express');
const path = require('path');
const app = express();
​
const staticRoot = path.resolve(__dirname, '../public');
​
const expressStaticGzip = require("express-static-gzip"); // ★引入express-static-gzip插件★
app.use(expressStaticGzip(staticRoot)); // ★开启Gzip压缩资源的响应★

拓展

如果你的静态文件是用 Nginx 管理的,那么只需要让 Nginx 根据请求来自己选择 .gz 文件输出。

利用 Nginx 中的http_gzip_static_module模块,不消耗 CPU 资源,在服务器端进行如下操作即可。

  • 执行nginx -t命令,查找nginx.conf配置文件所在位置

  • 执行cd命令,进入该配置文件所在路径

  • 执行vi nginx.conf命令,修改该配置文件(添加如下代码)

    gzip_static on;
    
  • 执行nginx -s reload命令,刷新 Nginx,便可成功开启。

注意:Nginx 中的http_gzip_static_module模块,默认是不存在的。因此,我们必须提前在 Nginx 中自行添加上该模块。戳我查看详细教程

功能测试

成功开启“Gzip 压缩”且重新完成部署后,可利用如下方法查看是否开启成功。

  • 输入URL,访问对应的前端页面,并打开 Chrome 控制台

  • 进入 Network 菜单页,便可以看到具体有哪些静态资源应用了“Gzip 压缩”

image.png

  • 如果看不到上图标记处的信息,请戳 ○这里○ 查看解决方案!

参考文档

PS:本文内容仅供交流学习,转载请注明出处。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值