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

1、前言

最近在作项目的过程当中,发现随着项目愈来愈大。编译以后的包也愈来愈大。
image.pngjavascript

能够发现,足足有35M
image.pngcss

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

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

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

2、compression-webpack-plugin

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

引入方式也很简单webpack

yarn add compression-webpack-plugin --D

须要注意compression-webpack-plugin得和你项目中的webpack匹配,不然会出现问题。
通常对应图是nginx

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版本的。web

以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选项中的几个参数的含义。

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

image.png
image.png

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

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

三、algorithm:压缩方式。

通常能够选择gzip和brotliCompress两种,brotliCompress稍后会说到。

四、threshold:压缩阈值

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

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

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

六、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,否则浏览器会报错,空白页面。

2、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。

3、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