Vue 打包 chunk-vendors.js 文件过大导致页面加载缓慢解决方案

19,047 阅读2分钟

一、chunk-vendors.js 简介

  • 顾名思义,chunk-vendors.js 是捆绑所有不是自己的模块,而是来自其他方的模块的捆绑包,它们称为第三方模块或供应商模块。

  • 通常,它意味着(仅和)来自项目 /node_modules 目录的所有模块,会将所有 /node_modules 中的第三方包打包到 chunk-vendors.js 中。

  • 将所有的第三方包集中到一个文件,自然也会出现文件过大的问题。

二、chunk-vendors.js 文件大小分析

  • 新创建一个 vue 项目,通过打包之后运行到服务器,然后访问得到 chunk-vendors.js182 B

    image.png

  • 通过安装第三方组件,将 chunk-vendors.js 文件增大,安装第三方组件之后需要在 main.js 中导入,重新运行 npm run build 进行打包。

    • npm i --save ant-design-vue,安装完打包后瞬间到了 1.9 MB

      import Antd from 'ant-design-vue';
      import 'ant-design-vue/dist/antd.css';
      Vue.use(Antd);
      

    image.png

    • npm i element-ui -S,安装完打包后瞬间到了 2.6 MB

      import ElementUI from 'element-ui';
      import 'element-ui/lib/theme-chalk/index.css';
      Vue.use(ElementUI);
      

    image.png

    • 不要看后面的 Time 时间那么短,因为这是内网本机访问快,如果到了外网就跟服务器带宽、性能有关了,但是文件这么大,加载慢,那就需要拆开来进行分块加载,不是一味升级服务器解决问题,毕竟要钱的!

    • 附带还未进行分块分包加载时,打包得到的文件目录(jscss)

    image.png

    image.png

    image.png

三、方式一:compression-webpack-plugin 插件解决方案

四、方式二

  • 还有种是通过 webpack 前端配置,将第三方包分开打包,这样不会将所有第三方包都打包到 chunk-vendors.js 文件,如果第三方包中存在过大的文件,那也会很大。

  • 所以可以两者一起使用也是可以的,选择其中一种使用也可以,下面是两种一起使用,可以根据情况剔除选一种,或者都使用。

    const path = require('path');
    
    const webpack = require('webpack')
    const CompressionPlugin = require('compression-webpack-plugin')
    const zlib = require('zlib')
    const isProduction = process.env.NODE_ENV === 'production'
    
    module.exports = {
      devServer: {
        disableHostCheck: true
      },
      configureWebpack: {
        resolve: {
          alias: {
            '@': path.resolve(__dirname, './src'),
            '@i': path.resolve(__dirname, './src/assets'),
          }
        },
        plugins: [
          new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
          // 下面两项配置才是 compression-webpack-plugin 压缩配置
          // 压缩成 .gz 文件
          new CompressionPlugin({
            filename: '[path][base].gz',
            algorithm: 'gzip',
            test: /\.js$|\.css$|\.html$/,
            threshold: 10240,
            minRatio: 0.8
          }),
          // 压缩成 .br 文件,如果 zlib 报错无法解决,可以注释这段使用代码,一般本地没问题,需要注意线上服务器会可能发生找不到 zlib 的情况。
          new CompressionPlugin({
            filename: '[path][base].br',
            algorithm: 'brotliCompress',
            test: /\.(js|css|html|svg)$/,
            compressionOptions: {
              params: {
                [zlib.constants.BROTLI_PARAM_QUALITY]: 11
              }
            },
            threshold: 10240,
            minRatio: 0.8
          })
        ],
        // 开启分离 js
        optimization: {
          runtimeChunk: 'single',
          splitChunks: {
            chunks: 'all',
            maxInitialRequests: Infinity,
            minSize: 20000,
            cacheGroups: {
              vendor: {
                test: /[\\/]node_modules[\\/]/,
                name (module) {
                  // get the name. E.g. node_modules/packageName/not/this/part.js
                  // or node_modules/packageName
                  const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1]
                  // npm package names are URL-safe, but some servers don't like @ symbols
                  return `npm.${packageName.replace('@', '')}`
                }
              }
            }
          }
        }
      }
    }
    

五、其他方式

  • 比如将有些大的 jscss 通过 cdn 的方式链接,可以多种方案配合一起使用的。

  • 其他参考方案