首頁 > 軟體

使用vue打包時gzip壓縮的兩種方案

2022-06-24 18:00:46

開局一張圖:

可以看出,在專案部署後,我們的資原始檔請求都會保持原本大小,如果檔案過大,並且很多的情況下,會導致網路請求耗時,嚴重點可能阻塞後面的程序。

介紹兩種gzip壓縮的方式

1、打包的時候通過webpack設定生成對應的 .gz 檔案,瀏覽器請求xx.js/css等檔案時,伺服器返回對應的xxx.js.gz檔案;

2、瀏覽器請求xx.js檔案時,伺服器對xx.js檔案進行gzip壓縮後傳輸給瀏覽器。

webpack打包生成gz檔案

安裝外掛(compression-webpack-plugin):

npm install compression-webpack-plugin --save-dev

vue.config.js檔案進行webpack設定(沒有此檔案可以在專案根路徑建立一個檔案):

const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
        plugins: [
            new CompressionPlugin({
                algorithm: 'gzip', // 使用gzip壓縮
                test: /.js$|.html$|.css$/, // 匹配檔名
                filename: '[path].gz[query]', // 壓縮後的檔名(保持原檔名,字尾加.gz)
                minRatio: 1, // 壓縮率小於1才會壓縮
                threshold: 10240, // 對超過10k的資料壓縮
                deleteOriginalAssets: false, // 是否刪除未壓縮的原始檔,謹慎設定,如果希望提供非gzip的資源,可不設定或者設定為false(比如刪除打包後的gz後還可以載入到原始資原始檔)
            }),
        ],
    },
};

這裡對js、html、css檔案進行了壓縮處理,並沒有進行圖片壓縮,因為圖片壓縮並不能實際減少檔案大小,反而會導致打包後生成很多同大小的gz檔案,得不償失。

當然了,上文提到過,瀏覽器請求xx.js/css等檔案時,伺服器返回對應的xxx.js.gz檔案,所以還需要在伺服器設定一個屬性,以期望它能正常返回我們需要的gz檔案。

這裡拿nginx舉例(nginx.conf檔案):

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    #tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    gzip_static on;
    server {
        listen       8462;
        server_name  localhost;
        location / {
            root   dist;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

其中gzip_static on這個屬性是靜態載入原生的gz檔案。

看下效果:

gzip壓縮比率在5-6倍,nginx設定了靜態gz載入後,瀏覽器也返回的是gz檔案,這樣就會請求小檔案而不會導致請求卡執行緒,並且,因為保留了原始檔,所以當我們刪除gz後,瀏覽器會自動去請求原始檔案,而不會導致介面出現任何問題(如圖二)。

靜態載入gz檔案主要是依託於下面的請求頭:

伺服器線上gzip壓縮

前端不用進行任何設定,也不用webpack生成gz檔案,伺服器進行處理,拿nginx舉例:

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    #tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    # 開啟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;
    server {
        listen       8462;
        server_name  localhost;
        location / {
            root   dist;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

上面有一些關於gzip的設定,首先是開啟gzip,設定緩衝區大小,壓縮的等級,需要壓縮的檔案等(如果需要更詳細的設定,可以檢視nginx的設定檔案),看下效果:

響應頭中會攜帶gzip壓縮設定,每次請求xx.js檔案,伺服器都會進行實時壓縮。

兩種方案的優缺點:

1、webpack打包,然後直接使用靜態的gz,缺點就是打包後檔案體積太大,但是不耗伺服器效能;

2、使用nginx線上gzip,缺點就是耗效能,需要實時壓縮,但是vue打包後的檔案體積小。

這裡可能有些同學就要問題,我想在有gz檔案的時候進行靜態壓縮,不存在gz檔案的時候進行線上壓縮而不是載入原始檔,要怎麼做呢?

簡單,兩種設定都寫上即可。

gzip on;
gzip_static on;
gzip_comp_level 2;
gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;  

首先,gzip_static的優先順序高,會先載入靜態gz檔案,當同目錄下不存在此檔案的時候,會執行線上壓縮的命令。

有些小夥伴就會納悶,既然都開啟的情況下,我們怎麼區分使用了靜態載入還是線上壓縮呢?

響應頭的Content-Edcoding:gzip表示gzip壓縮已經生效,而Etag中只有簡單字元表示靜態資源載入,而前面帶 W/ 表示啟動了線上壓縮。

看下圖:

就是兩種gzip壓縮的方案了。

vue專案開啟gzip壓縮

前端設定

拆完包之後,我們再用gzip做一下壓縮 安裝compression-webpack-plugin

// yarn add compression-webpack-plugin -D
// 在vue.congig.js中引入並修改webpack設定
const CompressionPlugin = require('compression-webpack-plugin')
configureWebpack: (config) => {
        if (process.env.NODE_ENV === 'production') {
            // 為生產環境修改設定...
            config.mode = 'production'
            return {
                plugins: [new CompressionPlugin({
                    test: /.js$|.html$|.css/, //匹配檔名
                    threshold: 10240, //對超過10k的資料進行壓縮
                    deleteOriginalAssets: false //是否刪除原檔案
                })]
            }
        }

後端設定

在伺服器我們也要做相應的設定 如果傳送請求的瀏覽器支援gzip,就傳送給它gzip格式的檔案 我的伺服器是用express框架搭建的 只要安裝一下compression就能使用

const compression = require('compression')
app.use(compression())  // 在其他中介軟體使用之前呼叫

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com