前端项目时因chunk-vendors过大导致首屏加载太慢,Vue Build时chunk-vendors的优化方案...

1、compression-webpack-plugin插件打包.gz文件

  • 安装插件 也可以指定版本 我这里下载的是1.1.2版本的,试过更高的版本会有ES6语法的报错,因为我node使用的是v12,如果node版本更高可以尝试更高版本

  • npm install --save-dev compression-webpack-plugin
    npm install --save-dev compression-webpack-plugin@1.1.2
    或者
    
    yarn add compression-webpack-plugin --save-dev
    
    

    解决 TypeError: Cannot read property ‘tapPromise‘ of undefined

    在使用 compression-webpack-plugin 插件时报这个错误,原因是版本问题。
    
    ERROR TypeError: Cannot read property 'tapPromise' of undefined
    TypeError: Cannot read property 'tapPromise' of undefined
    
    安装插件的时候默认最新版本,但是可能脚手架还不支持这个版本,所以需要降低插件版本进行使用,这边在安装的时候最新版本为 v9.2.0,降到 v6.1.1 进行使用
    
     npm install compression-webpack-plugin@6.1.1
    
    
    
    vue.config.js配置插件 
    module.exports = {
      chainWebpack: config => {
        const CompressionWebpackPlugin = require('compression-webpack-plugin')
        if (process.env.NODE_ENV === 'production') {
            config.plugin('CompressionPlugin').use(
            	new CompressionWebpackPlugin({
                test: /\.(js|css)$/,
                threshold: 10240, // 超过10kb的文件就压缩
          			deleteOriginalAssets:fale, // 删除压缩后的源文件
          			minRatio: 0.8
              })
            )
       	}
      }
    }
    
    

    2、nginx配置:

  • 完整示例
    server {
        listen 80;
        # gzip config
        gzip on;
        gzip_min_length 1k;
        gzip_comp_level 9;
        gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
        gzip_vary on;
        gzip_disable "MSIE [1-6]\.";
    
        root /usr/share/nginx/html;
    
        location / {
            # 用于配合 browserHistory 使用
            try_files $uri $uri/ /index.html;
    
            # 如果有资源,建议使用 https + http2,配合按需加载可以获得更好的体验 
            # rewrite ^/(.*)$ https://preview.pro.loacg.com/$1 permanent;
    
        }
        location /api {
            proxy_pass https://preview.pro.loacg.com;
            proxy_set_header   X-Forwarded-Proto $scheme;
            proxy_set_header   Host              $http_host;
            proxy_set_header   X-Real-IP         $remote_addr;
        }}server {
      # 如果有资源,建议使用 https + http2,配合按需加载可以获得更好的体验 
      listen 443 ssl http2 default_server;
    
      # 证书的公私钥
      ssl_certificate /path/to/public.crt;
      ssl_certificate_key /path/to/private.key;
    
      location / {
            # 用于配合 browserHistory 使用
            try_files $uri $uri/ /index.html;
    
      }
      location /api {
          proxy_pass https://preview.pro.loacg.com;
          proxy_set_header   X-Forwarded-Proto $scheme;
          proxy_set_header   Host              $http_host;
          proxy_set_header   X-Real-IP         $remote_addr;
      }}
    
    
    # gzip config gzip on; gzip_min_length 1k; gzip_comp_level 9; gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; gzip_vary on; gzip_disable "MSIE [1-6]\.";
    

    附录

    配置项释义:

  • # 开启服务器实时gzip
      gzip on;
      
      # 开启静态gz文件返回
      gzip_static on;
      
      # 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
      gzip_min_length 1k;
      
      # 设置压缩所需要的缓冲区大小     
      gzip_buffers 32 4k;
    
    # 设置gzip压缩针对的HTTP协议版本
      gzip_http_version 1.0;
    
      # gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
      gzip_comp_level 7;
    
      # 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
      gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
    
      # 是否在http header中添加Vary: Accept-Encoding,建议开启
      gzip_vary on;
    
      # 禁用IE 6 gzip
      gzip_disable "MSIE [1-6]\."; 
    

     实际成功实例

  • vue.config.js

  • module.exports = {
      publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
      chainWebpack: config => {
        const svgRule = config.module.rule('svg')
        const CompressionWebpackPlugin = require('compression-webpack-plugin')
        svgRule.uses.clear()
        svgRule
          .test(/\.svg$/)
          .use('svg-sprite-loader')
          .loader('svg-sprite-loader')
    
          if (process.env.NODE_ENV === 'production') {
              config.plugin('CompressionPlugin').use(
                  new CompressionWebpackPlugin({
                      test: /\.(js|css)$/,
                      threshold: 10240, // 超过10kb的文件就压缩
                      deleteOriginalAssets:false, // 删除压缩后的源文件
                      minRatio: 0.8
                  })
              )
          }
    
      },
      productionSourceMap: false,
      devServer: {
        open: true,
        port: 8001,
        overlay: {
          errors: true,
          warnings: true
        }
      },
    
    

     打包后的文件

  • nginx.conf 

  •     #gzip  on;
    
        server {
            listen       80;
            server_name  localhost;
            #开启gzip
            gzip  on;  
            #低于1kb的资源不压缩 
            gzip_min_length 1k;
            #压缩级别1-9,越大压缩率越高,同时消耗cpu资源也越多,建议设置在5左右。 
            gzip_comp_level 5; 
            #需要压缩哪些响应类型的资源,多个空格隔开。不建议压缩图片.
            gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;  
            #配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
            gzip_disable "MSIE [1-6]\.";  
            #是否添加“Vary: Accept-Encoding”响应头
            gzip_vary on;		
    
            #charset koi8-r;
    
            #access_log  logs/host.access.log  main;
    
            location / {
                root   /home/vue/dist;
                index  index.html index.htm;
            }
    
            #error_page  404              /404.html;
    
            # redirect server error pages to the static page /50x.html
            #
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
    
            # proxy the PHP scripts to Apache listening on 127.0.0.1:80
            #
            #location ~ \.php$ {
            #    proxy_pass   http://127.0.0.1;
            #}
    
            # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
            #
            #location ~ \.php$ {
            #    root           html;
            #    fastcgi_pass   127.0.0.1:9000;
            #    fastcgi_index  index.php;
            #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            #    include        fastcgi_params;
            #}
    
            # deny access to .htaccess files, if Apache's document root
            # concurs with nginx's one
            #
            #location ~ /\.ht {
            #    deny  all;
            #}
        }
    
    

     重启nginx

  • ./nginx -s reload  

  • 以下资料还没试过,有需要可以试试

  • 通过以上处理,在网页访问时,chunk-vendors.js 显示为2.3M,加载还是需要2秒左右,还是不太能接受。

    于是需要进一步查询项目还有哪些无用的大文件依赖,于是通过以下方法来定位大依赖:
    通过 webpack-bundle-analyzer 插件来分析依赖,该插件可以很清晰的看清楚 chunk-vendors.js 中包含了哪些依赖和哪些依赖是很大的,然后进一步分析这些依赖是否真的必要,如果没有必要就直接拿掉,最终,拿掉了三个1M多的依赖,直接让 chunk-vendors.js 从7.7M下降到了3.1M,gz压缩后只有900多kb,加载大概在700毫秒左右。

    具体操作如下:
    1 引入 webpack-bundle-analyzer 插件

    1
    npm install --save-dev webpack-bundle-analyzer

    2 修改 vue.config.js,相应位置加入以下代码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
    module.exports = {
    configureWebpack: config => {
    return {
    plugins: [
    new BundleAnalyzerPlugin()
    ]
    }
    }
    }