前端性能之压缩(拒绝各种没有试验的复制、粘贴)

寒水寺一禅
English

一、前言

最近在做项目的过程中,发现随着项目越来越大。编译之后的包也越来越大。
image.png

可以发现,足足有35M
image.png

之后,进入static下的js文件夹。

image.png
发现有两个文件,一个4M,一个13M,比其他的都大。

于是便在网上搜索各种提升页面及接口响应速度快的办法。无奈的是,网上大多都是从别人那里复制粘贴的帖子。最后也只能自己动手搞。

二、compression-webpack-plugin

言归正传。经过查询,发现前端有个库。compression-webpack-plugin

引入方式也很简单

yarn add compression-webpack-plugin --D

需要注意compression-webpack-plugin得和你项目中的webpack匹配,否则会出现问题。
一般对应图是

compression-webpack-plugin是8.x,  则webpack需要5.x
compression-webpack-plugin是7.x,  则webpack需要5.x
compression-webpack-plugin是6.x,  则webpack需要4.x或者5.x
compression-webpack-plugin是5.x,  则webpack需要4.x或者5.x

比如你项目中的webpack是4.x的,那么compression-webpack-plugin只能用5和6的。不能用7和8版本的。

以vue-cli3.x为例。

const CompressionPlugin = require("compression-webpack-plugin");


...其他代码
configureWebpack:{
  plugins:[
    new CompressionWebpackPlugin({
      test: /\.(js|css)?$/i, // 哪些文件要压缩
      filename: "[path][base].gz", // 压缩后的文件名
      algorithm: "gzip", // 使用gzip压缩
      threshold: 10240, //大于 10240字节,既10k时
      minRatio: 0.8,  //压缩率
      deleteOriginalAssets: true, //是否删除原本的js
    });
  ]
}
...其他代码

先来解释下CompressionWebpackPlugin选项中的几个参数的含义。

1、test:是个正则表达式,表示哪些文件需要压缩。这里我们选择以.js和.css结尾的文件。这样的话下面的文件都在范围内。

image.png
image.png

2、filename:表示压缩之后的文件名,后缀必须为.gz(是gzip的文件格式),path和base表示,会在压缩时,把源文件的名称和路径都携带上。比如

index.9b65b390.js   //需要压缩的源文件
index.9b65b390.js.gz   //压缩之后的文件。

3、algorithm:压缩方式。

一般可以选择gzip和brotliCompress两种,brotliCompress稍后会说到。

4、threshold:压缩阈值

表示文件的大小超过定义的字节,就会压缩

threshold: 10240表示,超过10240个字节,也就是超过10k是压缩。

5、minRatio这个没试出来怎么个用法,后面补充。

6、deleteOriginalAssets:表示是否删除源文件。

网上百分之90全写的false。

那么咱们假如有两个文件

index.9b65b390.js  
index.9b65b390.js.gz 

如果deleteOriginalAssets:true,最后只剩余index.9b65b390.js.gz

效果是这样的
image.png

最后查看dist,已经从原来的37M,降到了19M
image.png

而如果deleteOriginalAssets为false,那么最终的源文件和gz文件都在。
image.png

最后查看dist,发现比我没压缩前的37M都大。达到了41M
image.png

那我图啥呢?图37M不够大吗?

所以如果我们想要让dist变小,那就必须选deleteOriginalAssets为true。
但是注意一点,在development模式下,这个要false,不然浏览器会报错,空白页面。

二、nginx

前端打包好gz后,还需要后端进行配置,以nginx为例。
只需要加一行代码即可。

image.png

有的朋友会说。"gzip true"也可以呀。

没错,gzip true确实可以。像这样
image.png

但是gzip是动态压缩,比如你的接口返回大量数据或者返回静态的大js文件。服务器会根绝你gzip_min_length的配置,去实时压缩,然后给你返回。在这个过程中,服务器是要消耗性能和资源的。你压缩的越小。服务器处理的越慢,相应的你http会等待更长。

而gzip_static是指,直接从服务器上去找.gz的文件。如果有直接返回。没有就退而求其次找源文件。这个过程,服务器响应是很快速的。

你也可以都配置上。gzip_static优先于gzip

location / {
       root   html;
       index  index.html; 
       gzip_static on; 
}


gzip  on;
gzip_min_length 10k;
gzip_comp_level 1;
gzip_types text/plain application/json application/javascript text/css;
gzip_vary on;

image.png
打开浏览器我们可以看到content-encoding为gzip,文件大小为4.2M,比我们刚开始没压缩的13M小了太多了。

最后,gz的文件返回后,不需要显式的处理,浏览器会自动解压。
image.png

查看浏览器我们发现,Accept-Encoding定义的浏览器可以接受的压缩格式为gzip, deflate, br三种。而服务器返回给我们的格式是 Content-Encoding:gzip,这OK,浏览器可以处理。

image.png
你鼠标放到4.2M这个位置上,会有个类似于title的东西,提示只有4.2M是通过网络传输的。但是实际上源文件有13.9M。

三、Brotli

刚才在CompressionWebpackPlugin中说algorithm时,除了gzip,还有个压缩方式,那就是brotli。

它是一种更加高效的压缩方式。而且各大浏览器基本都支持,但是也严格,需要https才可以,http中不支持Brotli,

image.png
image.png

下面是vue的配置

const CompressionPlugin = require("compression-webpack-plugin");
const zlib = require("zlib");

...其他代码
configureWebpack:{
  plugins:[
    new CompressionWebpackPlugin({
      test: /\.(js|css)?$/i, 
      filename: "[path][base].br",
      algorithm: "brotliCompress", 
      threshold: 10240, 
      minRatio: 0.8, 
      deleteOriginalAssets: true, //是否删除原本的js
      compressionOptions: {
          params: {
              [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
          },
      },
    });
  ]
}
...其他代码

压缩后,我们发现,比刚才gzip压缩的更小
image.png
image.png

整个dist的大小,从gzip的19M,缩小到了16M
image.png
image.png

然后设置nginx的配置。


location / {
       root   html;
       index  index.html; 
       brotli_static on; 
}


brotli on;  
brotli_comp_level 6;
brotli_buffers 16 8k;
brotli_min_length 20;
brotli_types *;  

注意下nginx默认没有brotli模块,需要安装,编译下(后端知道怎么弄,前端不用关心)

然后打开浏览器我们会看到
image.png

image.png

阅读 4.9k

小李子的前端
热爱前端的菜鸟,怀揣梦想的小白

人生短短急个球!

2.1k 声望
72 粉丝
0 条评论

人生短短急个球!

2.1k 声望
72 粉丝
文章目录
宣传栏