性能优化 - Gzip代码压缩 - 提升页面加载性能

684 阅读3分钟

一、 问题背景

最近发现Vue打包chunk-vendors.js文件过大,页面加载有点慢。为了减少加载时间,提升用户体验,因此打包时我们使用了gzip压缩(需要服务端配合修改nginx配置)。

二、为什么要用Gzip压缩?

Content-Encoding - MDN

  1. 主流浏览器都支持Gzip压缩,只有极少数的手机轻量浏览器可能不支持。

  2. 压缩效果好,使用Gzip压缩后文件大小能减少60%-70%左右。

    使用gzip压缩后文件大小是原来的30%左右

三、 Gzip工作原理

  1. 浏览器请求url,并在请求头重设置属性accept-encoding:gzip。表明浏览器支持gzip,这个参数是浏览器自动会携带的请求头信息。
  2. 服务器收到浏览器发送的请求之后,服务器会返回压缩后的文件,并在响应头中包含content-encoding:gzip;如果没有压缩文件,服务器会返回未压缩的请求文件。
  3. 浏览器接收到服务器的响应,根据content-encoding:gzip响应头使用gzip策略去解压压缩后的资源,通过content-type内容类型决定怎么编码读取该文件的内容。

四、Gzip压缩的几种方案

1. Nginx实时压缩

浏览器请求资源时,Nginx服务器对文件进行gzip压缩后返回给浏览器。前端不用做任何修改正常打包,但这样会消耗服务器性能。

Nginx开启gzip压缩,代码如下:

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

sendfile        on;
#tcp_nopush     on;
client_max_body_size 100m;
#keepalive_timeout  0;
keepalive_timeout  120;

# 开启gzip
gzip  on;

# 设置缓冲区大小
gzip_buffers 4 16k;

#压缩级别官网建议是6
gzip_comp_level 6;

#压缩的类型
gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php;

#允许压缩的文件最小字节
gzip_min_length 10k;
server {
    listen       80;
}
    
}}
指令格式说明
gzipgzip on | off控制是否开启gzip,默认开启
gzip_min_lengthgzip_min_length length大于length的响应才压缩,默认为20字节
gzip_http_versiongzip_http_version 1.0 | 1.11.1的请求开启压缩功能
gzip_buffersgzip_buffers number size设置gzip申请内存的大小,申请number个大小为size的空间
gzip_comp_levelgzip_comp_level_ level设置压缩等级,1-9,1表示压缩程度最低,压缩率最高。9表示相反,最费时间。
gzip_typesgzip_types mine-types根据mine-type类型进行压缩,可以取值text/plain等。

nginx配置里的gzip属性和gzip_static 属性可以同时设置为ongzip_static的优先级高,如果存在.gz静态资源会优先时候静态资源返回,若不存在,会实时生成压缩文件。

如何区分使用了静态加载还是在线压缩?

响应头的Content-Edcoding:gzip表示gzip压缩已经生效,而Etag中只有简单字符表示静态资源加载,而前面带 W/表示启动了在线压缩。

2. webpack配置(前端打包压缩)

打包时通过webpack配置生成的对应的.gz文件,浏览器请求文件后会自动解压为js或者css等资源文件。打包借助compression-webpack-plugin插件打包出.gz文件。

安装插件:npm install compression-webpack-plugin—save-dev

// vue.config.js

const { defineConfig } = require('@vue/cli-service')
const CompressionPlugin = require("compression-webpack-plugin"); // 开启gzip压缩, 按需引用
module.exports = defineConfig({
  configureWebpack: {
    plugins: [
      new CompressionPlugin({
        algorithm: 'gzip', // 使用gzip压缩
        test: /.js$|.html$|.css$/, // 匹配文件名
        filename: '[path][base].gz[query]', // 压缩后的文件名(保持原文件名,后缀加.gz)
        minRatio: 1, // 压缩率小于1才会压缩
        threshold: 10240, // 对超过10k的数据压缩
        deleteOriginalAssets: false, // 是否删除未压缩的源文件,谨慎设置,如果希望提供非gzip的资源,可不设置或者设置为false(比如删除打包后的gz后还可以加载到原始资源文件)
      }),
    ]
  }
})

可以通过配置deleteOriginalAssets:true,删除未打包资源,但推荐保留未打包资源

此时Nginx服务器只需要配置:gzip_static on

3. Nodejs启用gzip

nodejs启用gzip相对来说比较简单,以express框架为例如何启用gzip

npm install compression
npm install @types/compression --save-dev
import compression from 'compression'
...
const app = express();
// 尽量在其他中间件前面
app.use(compression({level:5}));
...

参考文章 ☞ 前端性能之gzip压缩