vue 打包性能优化总结

所谓的性能优化在我看来就是访问速度的一个提升,那如何提升呢?下面是我的一些粗鄙的见解,请参考:

用过vue 的开发者应该都晓得开发vue 项目随着项目开发愈久用到的插件越来越多的情况下打包后的chunk-vendors.js文件会越来越大,这个是最常见的导致页面加载缓慢文件之一:

推荐两款常见的比较好用的分析工具:

1、vue ui(可参考此博客vue ui 如何操作的)

2、webpack-bundle-analyzer打包文件分析工具webpack-bundle-analyzer

chunk-vendor.js文件说明: 来自第三方插件,也就是node_modules/ 下所有用到的依赖包集合的打包文件的输出

下面是个人项目vue,config.js部分配置文件供参考:有更好建议请留言赐教

分包方式优化chunk-vendors.js 过大问题

const { defineConfig } = require('@vue/cli-service');
const path = require('path');
// const useCDNs = require('./useCDNs');
const webpack = require('webpack');
const CompressionPlugin = require('compression-webpack-plugin');
// const zlib = require('zlib');

function resolve(dir) {
  return path.join(__dirname, dir);
}

module.exports = defineConfig({
  transpileDependencies: true,
  productionSourceMap: false,
});
module.exports = {
  // productionSourceMap: false,
  publicPath: '/',
  parallel: false,
  pwa: { // pwa 缓存处理
    iconPaths: {
      favicon32: 'favicon.ico',
      favicon16: 'favicon.ico',
      appleTouchIcon: 'favicon.ico',
      maskIcon: 'favicon.ico',
      msTileImage: 'favicon.ico',
    },
  },
  // 不输出 map 文件,以加速生产环境构建
  chainWebpack: (config) => {
    config.module
      .rule('md')
      .test(/\.md/)
      .use('vue-loader')
      .loader('vue-loader')
      .end()
      .use('vue-markdown-loader')
      .loader('vue-markdown-loader/lib/markdown-compiler')
      .options({
        raw: true,
      });
    config.module.rule('svg').exclude.add(resolve('src/icons')).end();
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]',
      })
      .end();
  },
  configureWebpack: {
    resolve: {
      alias: {
        '@': path.resolve(__dirname, './src'),
        '@i': path.resolve(__dirname, './src/assets'),
      },
    },
    plugins: [
      new webpack.IgnorePlugin({
        resourceRegExp: /^\.\/locale$/,
        contextRegExp: /ElementPlus$/,
      }),
      new CompressionPlugin({  // 开启gzip压缩
        filename: '[path][base].gz',
        algorithm: 'gzip',
        test: /\.ts$|\.js$|\.css$|\.html$/,
        threshold: 10240,
        minRatio: 0.8,
      }),
    ],
    // 开启分离 js
    optimization: {
      runtimeChunk: 'single',
      splitChunks: {
        chunks: 'all',
        // maxInitialRequests: Infinity,
        // minSize: 20000,
        cacheGroups: {
          commons: {
            // split async commons chunk
            name: 'chunk-async-commons',
            minChunks: 2,
            priority: 40,
            chunks: 'async',
          },
          elementPlus: {
            name: 'chunk-elementPlus', // split elementUI into a single package
            priority: 30, // the weight needs to be larger than libs and app or it will be packaged into libs or app
            test: /[\\/]node_modules[\\/]_?element-plus(.*)/, // in order to adapt to cnpm
          },
        },
      },
    },
  },
  devServer: {
    //开发服务的一些处理
  },
};

依赖包通过cdn方式引入来优化项目打包过大问题:

弊端: cdn外链资源请求慢的情况下,或者cdn当掉的话,那么项目启动肯定是会直接当掉或者一直加载中

/** @file useCDNs.js */

/** @typedef {string} ModuleName 模块名   */
/** @typedef {string} ModuleRefer 模块在全局的引用   */
/** @typedef {string} ElementTem 元素模板   */
/** @typedef {{mod:ModuleName;refer:ModuleRefer;el:ElementTem}} CDNItem  cdn 项目 */

/**
 * cdn 使用函数。
 *
 * 此函数可以在指定开发环境中,指定某些模块作为外部依赖出现,并把准备好的第三方 cdn 模板以 `cdns` 参数通过 HtmlWebpackPlugin 插件插入到 `public/index.html` 文件中。
 * 你可以在 `public/index.html` 中使用 ejs 语法 <%= htmlWebpackPlugin.options.cdns %> 来插入准备好的 cdn。
 *
 * @param {import('webpack-chain')} config webpack-chain 实例
 * @param {CDNItem[]} cdns 传入需要使用的 cdn 数组
 * @param {string} env 什么环境下使用 cdn ,默认生产环境
 */
module.exports = function useCDNs(config, cdns = [], env = 'production') {
  if (process.env.NODE_ENV !== env) return;

  config.externals(
    cdns.reduce((prev, v) => {
      prev[v.mod] = v.refer;
      return prev;
    }, {})
  );

  config.plugin('html').tap((args) => {
    args[0].cdns = cdns.map((v) => v.el).join('');
    return args;
  });
};

在vue.config.js 中使用useCDNs.js将需要用的cdn资源注入
下面使用elemet-ui为例子:线上环境使用cdn方式,开发环境使用依赖方式、样式文件可以通过

在main.js/main.ts 中引入

const { defineConfig } = require('@vue/cli-service');
const path = require('path');
// const useCDNs = require('./useCDNs');
const webpack = require('webpack');
const CompressionPlugin = require('compression-webpack-plugin');
// const zlib = require('zlib');

function resolve(dir) {
  return path.join(__dirname, dir);
}

module.exports = defineConfig({
  transpileDependencies: true,
  productionSourceMap: false,
});
module.exports = {
  // productionSourceMap: false,
  publicPath: '/',
  parallel: false,
  pwa: {
    iconPaths: {
      favicon32: 'favicon.ico',
      favicon16: 'favicon.ico',
      appleTouchIcon: 'favicon.ico',
      maskIcon: 'favicon.ico',
      msTileImage: 'favicon.ico',
    },
  },
  // 不输出 map 文件,以加速生产环境构建
  chainWebpack: (config) => {
    // 只在生产环境使用 cdn
    useCDNs(config, {
      mod: 'moment',
      refer: 'moment',
      el: 'https://cdn.jsdelivr.net/npm/[email protected]/moment.min.js',
    });
  configureWebpack: {
    resolve: {
      alias: {
        '@': path.resolve(__dirname, './src'),
        '@i': path.resolve(__dirname, './src/assets'),
      },
    },
    plugins: [
      new webpack.IgnorePlugin({
        resourceRegExp: /^\.\/locale$/,
        contextRegExp: /ElementPlus$/,
      }),
      new CompressionPlugin({
        filename: '[path][base].gz',
        algorithm: 'gzip',
        test: /\.ts$|\.js$|\.css$|\.html$/,
        threshold: 10240,
        minRatio: 0.8,
      }),
    ],
    // 开启分离 js
    optimization: { // 如果打包出的chunk-vender文件过大的话使用它
      runtimeChunk: 'single',
      splitChunks: {
        chunks: 'all',
        // maxInitialRequests: Infinity,
        // minSize: 20000,
        cacheGroups: {
          commons: {
            // split async commons chunk
            name: 'chunk-async-commons',
            minChunks: 2,
            priority: 40,
            chunks: 'async',
          },
          elementPlus: {
            name: 'chunk-elementPlus', // split elementUI into a single package
            priority: 30, // the weight needs to be larger than libs and app or it will be packaged into libs or app
            test: /[\\/]node_modules[\\/]_?element-plus(.*)/, // in order to adapt to cnpm
          },
        },
      },
    },
  },
  devServer: {
  },
};

vue 打包性能优化总结_第1张图片

简单记录有问题可私信解决 

你可能感兴趣的:(vue,配置,webpack,vue.js,前端,javascript)