webpack vue-cli 启动编译慢

场景:webpack vue-cli 启动编译慢

# 耗时时间
npm install speed-measure-webpack-plugin --save-dev
# 配置 vue.config.js
module.exports = {
    chainWebpack: (config) => {
        config.plugin('xcTime').use(SpeedMeasurePlugin);
    })
};
# 耗时详情
    DONE  Compiled successfully in 132420ms

    SMP  ?
    General output time took 2 mins, 12.39 secs   

    SMP  ?  Loaders
    @dcloudio/vue-cli-plugin-uni, and
    css-loader, and
    @dcloudio/vue-cli-plugin-uni, and
    @dcloudio/vue-cli-plugin-uni, and
    postcss-loader, and
    @dcloudio/vue-cli-plugin-uni, and
    @dcloudio/vue-cli-plugin-uni, and
    @dcloudio/vue-cli-plugin-uni, and
    unplugin took 1 min, 43.082 secs
    module count = 266
    modules with no loaders took 1 min, 34.62 secs
    module count = 871
    @dcloudio/vue-cli-plugin-uni, and
    @dcloudio/vue-cli-plugin-uni, and
    @dcloudio/vue-cli-plugin-uni, and
    eslint-loader, and
    unplugin took 1 min, 34.5 secs
    module count = 272
    babel-loader, and
    @dcloudio/vue-cli-plugin-uni, and
    @dcloudio/vue-cli-plugin-uni, and
    eslint-loader, and
    unplugin took 53.99 secs
    module count = 195
    url-loader took 36.37 secs
    module count = 77
    babel-loader, and
    ts-loader, and
    @dcloudio/vue-cli-plugin-uni, and
    eslint-loader, and
    unplugin took 32.92 secs
    module count = 15
    babel-loader, and
    @dcloudio/vue-cli-plugin-uni took 14.12 secs
    module count = 51
    @dcloudio/vue-cli-plugin-uni, and
    @dcloudio/vue-cli-plugin-uni, and
    css-loader, and
    @dcloudio/vue-cli-plugin-uni, and
    postcss-loader, and
    @dcloudio/vue-cli-plugin-uni, and
    @dcloudio/vue-cli-plugin-uni, and
    @dcloudio/vue-cli-plugin-uni, and
    @dcloudio/vue-cli-plugin-uni took 10.3 secs
    module count = 12
    @dcloudio/vue-cli-plugin-uni, and
    @dcloudio/vue-cli-plugin-uni took 6.16 secs

thread-loader的使用

# 多核编译
npm install thread-loader --save-dev
# 配置 vue.config.js

    const ThreadLoader = require('thread-loader');
    const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');

    const os = require('os');
    // cpu核数
    const threads = os.cpus().length;

    const options = {
    // 产生的 worker 的数量,默认是 (cpu 核心数 - 1),或者,
    // 在 require('os').cpus() 是 undefined 时回退至 1
    workers: threads - 1,

    // 一个 worker 进程中并行执行工作的数量
    // 默认为 20
    workerParallelJobs: 50,

    // 额外的 node.js 参数
    workerNodeArgs: ['--max-old-space-size=1024'],

    // 允许重新生成一个僵死的 work 池
    // 这个过程会降低整体编译速度
    // 并且开发环境应该设置为 false
    poolRespawn: false,

    // 闲置时定时删除 worker 进程
    // 默认为 500(ms)
    // 可以设置为无穷大,这样在监视模式(--watch)下可以保持 worker 持续存在
    poolTimeout: 2000,

    // 池分配给 worker 的工作数量
    // 默认为 200
    // 降低这个数值会降低总体的效率,但是会提升工作分布更均一
    poolParallelJobs: 50,

    // 池的名称
    // 可以修改名称来创建其余选项都一样的池
    name: 'my-pool',
    };
    ThreadLoader.warmup(options, [
    // 加载模块
    // 可以是任意模块,例如
    'babel-loader',
    'ts-loader',
    'css-loader',
    'eslint-loader',
    'url-loader',
    'postcss-loader',
    ]);
    module.exports = {
        configureWebpack: {
            devtool: process.env.DODE_ENV === 'production' ? 'source-map' : 'eval-cheap-source-map',
        },
        chainWebpack: (config) => {
        [
            // 'mjs',
            // 'vue', // error: compiler.parseComponent is not a function
            // 'images', // error: this.emitFile is not a function
            'svg',
            'media',
            'fonts',
            // 'pug',
            // 'css',
            // 'postcss',
            // 'scss',
            // 'sass',
            // 'less',
            // 'stylus',
            // 'js', // error: Cannot read property 'options' of undefined
            'eslint',
            'ts', // error: Cannot read property 'options' of undefined
            'tsx',
            // 'jsx',
            ].forEach((rule) => {
            // 多核编译
            const originUse = config.module.rule(rule).toConfig().use;
            if (originUse) {
                // 2、添加 loader
                const newLoader = [
                { loader: 'thread-loader', options },
                { loader: 'cache-loader' },
                // ...originUse,
                ...originUse.map((item) => {
                    if (item.loader.includes('ts-loader')) {
                    item.options.happyPackMode = true;
                    item.options.transpileOnly = true;
                    return item;
                    }
                    return item;
                }),
                ];
                // originUse.unshift(newLoader);
                // 3、清空原来的 loader
                config.module.rule(rule).uses.clear();
                // 4、重新设置新的 loader
                config.module.rule(rule).merge({ use: newLoader });
            }
            });
            config.plugin('xcTime').use(SpeedMeasurePlugin);

            // production only
            config.when(process.env.NODE_ENV === 'production', (config_) => {
            // terser-webpack-plugin
            config_.optimization.minimizer('terser').tap((args) => {
                args[0].parallel = threads > 1; // 多线程压缩js
                args[0].cache = true;
                args[0].terserOptions.nameCache = 'terser-cache';
                args[0].terserOptions.compress.warnings = true;
                args[0].terserOptions.compress.drop_debugger = true;
                args[0].terserOptions.compress.drop_console = true;
                return args;
            });
            });
        })
    };

优化后耗时

# 提升30s, 只做了 'eslint-loader', 'url-loader' 多线程编译优化

DONE  Compiled successfully in 102831ms  

#  .vue .js/ts 报错大概和其它冲突(没有搞定),这部分优化后速度应该大幅度提升
'vue', // error: compiler.parseComponent is not a function
'js', // error: Cannot read property 'options' of undefined
'ts', // error: Cannot read property 'options' of undefined

cache 优化,首次编译启动慢一点,后面差量编译

# 耗时
DONE  Compiled successfully in 4011ms    


# 详细
1. npm install hard-source-webpack-plugin
2. vue.config.js 

 const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');

 module.exports = {
   configureWebpack: (config) => {
     config.devtool =
       process.env.DODE_ENV === 'production'
         ? 'cheap-module-source-map'
         : 'cheap-module-eval-source-map';
     config.module.noParse =
       /^(vu|vue-router|vuex|vuex-router-sync|lodash|echarts|axios|element-ui)$/;
   },
   chainWebpack: (config) => {
     config.when(process.env.NODE_ENV !== 'production', (config_) => {
       config_.plugin('hard-source').use(
         new HardSourceWebpackPlugin({
           root: process.cwd(),
           directories: [],
           environmentHash: {
             root: process.cwd(),
             directories: [],
             files: ['package.json', 'yarn.lock', 'package-lock.json'],
           },
         }),
       );
       config_.plugin('hard-source-exclude').use(
         new HardSourceWebpackPlugin.ExcludeModulePlugin([
           {
             test: /mini-css-extract-plugin[\\/]dist[\\/]loader/,
           },
         ]),
       );
     });
   },
 };