webpack 打包优化

速度分析

1、安装速度分析插件:npm i -D speed-measure-webpack-plugin

  • 分析整个打包总耗时
  • 每个 plugin 和 loader 的耗时情况

2、修改 vue.config.js 配置文件:

// 导入速度分析插件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
// 实例化插件
const smp = new SpeedMeasurePlugin();
module.exports = {
    configureWebpack: smp.wrap({
        plugins: [
            // 这里是自己项目里需要使用到的其他插件
            new yourOtherPlugin()
        ]
    })
}

3、运行项目,查看打包速度

 SMP  
General output time took 16.98 secs

 SMP    Loaders
modules with no loaders took 16.057 secs
  module count = 544
css-loader, and
vue-loader, and
postcss-loader, and
sass-loader, and
cache-loader, and
vue-loader took 11.28 secs
  module count = 45
cache-loader, and
vue-loader, and
eslint-loader took 10.73 secs
  module count = 92
cache-loader, and
babel-loader, and
eslint-loader took 8.31 secs
  module count = 18
cache-loader, and
babel-loader, and
cache-loader, and
vue-loader took 8.1 secs
  module count = 41
cache-loader, and
vue-loader, and
cache-loader, and
vue-loader took 6.88 secs
  module count = 46
css-loader, and
postcss-loader took 4.12 secs
  module count = 30
url-loader took 3.93 secs
  module count = 35
cache-loader, and
babel-loader took 2.47 secs
  module count = 4
vue-style-loader, and
css-loader, and
postcss-loader took 0.142 secs
  module count = 30
vue-style-loader, and
css-loader, and
vue-loader, and
postcss-loader, and
sass-loader, and
cache-loader, and
vue-loader took 0.107 secs
  module count = 45
vue-loader, and
vue-style-loader, and
css-loader, and
postcss-loader, and
sass-loader, and
cache-loader, and
vue-loader, and
eslint-loader took 0.084 secs
  module count = 45
vue-loader, and
cache-loader, and
babel-loader, and
cache-loader, and
vue-loader, and
eslint-loader, and
eslint-loader took 0.053 secs
  module count = 41
html-webpack-plugin took 0.036 secs
  module count = 1

体积分析

1、npm i -D webpack-bundle-analyzer 2、修改 vue.config.js 配置文件

// 导入速度分析插件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
// 导入体积分析插件
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
// 实例化速度分析插件
const smp = new SpeedMeasurePlugin();
module.exports = {
    configureWebpack: smp.wrap({
        plugins: [
            // 实例化体积分析插件
            new BundleAnalyzerPlugin()
        ]
    })
}

3、构建完成后会在 8888 端口展示大小,其中黄色块 chunk-vendors 文件占比最大,为 2.62MB

打包优化

多进程多实例构建,资源并行解析

多进程构建的方案比较知名的有以下三个:thread-loader (推荐使用这个)、parallel-webpack、HappyPack

npm i -D thread-loader

在 vue.config.js 配置文件中使用该 loader:

// 导入速度分析插件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
// 实例化插件
const smp = new SpeedMeasurePlugin();
module.exports = {
    configureWebpack: smp.wrap({
        module: {
            rules: [
                {
                    test: /\.js$/,
                    use: ['thread-loader']
                }
            ]
        }
    })
}

构建花费的时间 15.87 secs,相较于之前提升了 1.11s

公用代码提取,使用 CDN 加载

对于vue,vuex,vue-router,axios,echarts,swiper等我们可以利用webpack的externals参数来配置,这里我们设定只需要在生产环境中才需要使用。配置 vue.config.js 如下:

// 导入速度分析插件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
// 导入体积分析插件
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
//判断是否为生产环境
const isProduction = process.env.NODE_ENV === 'production';
//定义 CDN 路径,这里采用 bootstrap 的 cdn
const cdn = {
  css: ["https://cdn.bootcdn.net/ajax/libs/vant/2.12.9/vant.min.js"],
  js: [
    "https://cdn.bootcss.com/vue/2.6.11/vue.min.js",
    "https://cdn.bootcss.com/vue-router/3.2.0/vue-router.min.js",
    "https://cdn.bootcss.com/vuex/3.4.0/vuex.min.js",
    "https://cdn.bootcss.com/axios/0.21.1/axios.min.js"
  ]
};
// 实例化插件
const smp = new SpeedMeasurePlugin();
module.exports = {
    chainWebpack: config => {
        // 生产环境配置
        if (isProduction) {
            // 生产环境注入 cdn
            config.plugin('html')
                .tap(args => {
                    args[0].cdn = cdn;
                    return args;
                });
        }
    },
    configureWebpack: smp.wrap({
        module: {
            rules: [
                {
                    test: /\.js$/,
                    use: ['thread-loader']
                }
            ]
        },
        plugins: [
            new BundleAnalyzerPlugin()
        ],
        //生产环境注入 cdn
        externals: isProduction && {
            'vue': 'Vue',
            'vuex': 'Vuex',
            'vue-router': 'VueRouter',
            'axios': 'axios',
        } || {}
    })
}

构建结果 8.48 secs ,比上次构建减少 7.39s


 SMP  
General output time took 8.48 secs

 SMP    Plugins
BundleAnalyzerPlugin took 0.205 secs

 SMP    Loaders
thread-loader took 7.23 secs
  module count = 535
css-loader, and
vue-loader, and
postcss-loader, and
sass-loader, and
cache-loader, and
vue-loader took 3.56 secs
  module count = 45
cache-loader, and
vue-loader, and
eslint-loader took 2.93 secs
  module count = 92
cache-loader, and
vue-loader, and
cache-loader, and
vue-loader took 2.63 secs
  module count = 46
cache-loader, and
babel-loader, and
thread-loader, and
cache-loader, and
vue-loader took 2.4 secs
  module count = 41
css-loader, and
postcss-loader took 2.23 secs
  module count = 30
url-loader took 1.72 secs
  module count = 35
modules with no loaders took 0.886 secs
  module count = 9
cache-loader, and
babel-loader, and
thread-loader, and
eslint-loader took 0.859 secs
  module count = 18
cache-loader, and
babel-loader, and
thread-loader took 0.689 secs
  module count = 4
vue-style-loader, and
css-loader, and
vue-loader, and
postcss-loader, and
sass-loader, and
cache-loader, and
vue-loader took 0.074 secs
  module count = 45
vue-style-loader, and
css-loader, and
postcss-loader took 0.056 secs
  module count = 30
vue-loader, and
cache-loader, and
babel-loader, and
thread-loader, and
cache-loader, and
vue-loader, and
eslint-loader, and
eslint-loader took 0.04 secs
  module count = 41
vue-loader, and
vue-style-loader, and
css-loader, and
postcss-loader, and
sass-loader, and
cache-loader, and
vue-loader, and
eslint-loader took 0.04 secs
  module count = 45
html-webpack-plugin took 0.027 secs
  module count = 1