前端性能之壓縮(拒絕各類沒有試驗的複製、粘貼)

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