缓慢的webpack构建时间(高级模块优化)

时间:2017-04-11 09:26:00

标签: webpack webpack-2

我们很难尝试迁移到webpack我们的项目,该项目目前基于requirejs。

在尝试使用webpack复制我们当前的项目状态几周后,我们遇到了性能问题。

我们使用的是webpack版本 2.3.3

目前我们有240个模块和58个块。

我们的问题是,当我们以 watch 模式启动webpack进行开发(或使用webpack-dev-server)时,每次修改文件时,我们都要等待大约10秒钟。

这是我们的webpack开发配置:

{
  context: path.resolve(__dirname),

  entry: {
      'app-std': [
        'main',
        'plugins/base-component',
        'controllers/base-controller',
        'widgets/base-widget',
        'usertiming'
      ]
  },

  output: {
    path: path.resolve('./dist/js'),
    filename: '[name].js',
    publicPath: '/js/'
  },

  resolve: {
    modules: ['public/js', 'node_modules'],
    alias: {
        'uuid': path.resolve(__dirname, 'public/vendor/uuid.js/dist/uuid.core.js'),
        'jsLogger': 'js-logger',
        'jqueryCookie': 'js-cookie',
        'jqueryValidation': path.resolve(__dirname, 'node_modules/jquery-validation/dist/jquery.validate.js'),
        'jQueryXDomainRequest': 'jquery-ajax-transport-xdomainrequest',
        'dust': 'dustjs-linkedin',
        'dust.core': 'dustjs-linkedin',
        'dustHelpers': 'dustjs-helpers',
        'bootstrapSelect': 'bootstrap-select',
        'bootstrapDropDown': path.resolve(__dirname, 'node_modules/bootstrap/js/dropdown.js')
    }
  },

module: {

    rules: [            
        {
            test: /\.jsx?$/,
            loader: 'babel-loader',
            exclude: /(node_modules)/,
            options: {
                presets: [['es2015', { modules: false }]/*, 'react'*/],
                plugins: ['syntax-dynamic-import'],
                cacheDirectory: true
            }
        }
    ]
},

plugins: [
    new webpack.DefinePlugin({
        'process.env': {
            'NODE_ENV': JSON.stringify('local')
        }
    }),
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery'
    }),
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
],

devtool: 'cheap-module-eval-source-map',

devServer = {
    https: true,
    port: 7070,
    host: '0.0.0.0',
    headers: { 'Access-Control-Allow-Origin': '*' }
},

stats: {
    chunks: true,
    chunkModules: true,
    modules: true
}

}

这些是初始构建的统计信息:

6185ms building modules
65ms sealing
2ms optimizing
1ms basic module optimization
12ms module optimization
7906ms advanced module optimization
1ms basic chunk optimization
0ms chunk optimization
1ms advanced chunk optimization
0ms module and chunk tree optimization
12ms module reviving
2ms module order optimization
3ms module id optimization
2ms chunk reviving
6ms chunk order optimization
9ms chunk id optimization
22ms hashing
0ms module assets processing
214ms chunk assets processing
2ms additional chunk assets processing
1ms recording
0ms additional asset processing
0ms chunk asset optimization
2ms asset optimization
192ms emitting

如果我们修改了我们的一个模块,webpack将重启并获得这些数字:

38ms building modules
38ms sealing
1ms optimizing
1ms basic module optimization
1ms module optimization
7470ms advanced module optimization
1ms basic chunk optimization
0ms chunk optimization
1ms advanced chunk optimization
0ms module and chunk tree optimization
3ms module reviving
0ms module order optimization
4ms module id optimization
3ms chunk reviving
1ms chunk order optimization
4ms chunk id optimization
14ms hashing
0ms module assets processing
1ms chunk assets processing
1ms additional chunk assets processing
0ms recording
0ms additional asset processing
1ms chunk asset optimization
0ms asset optimization
1ms emitting

在这两种情况下,大部分时间都是高级模块优化步骤。 我不明白为什么在非生产版本中存在高级优化,我不知道为什么要花这么多时间。

我想知道是否有任何方法可以深入挖掘这个耗时的步骤,以及是否可以在开发模式中禁用该优化。

谢谢!

3 个答案:

答案 0 :(得分:1)

我们的团队也有同样的问题。我们已经确定减速是由使用require.ensure引起的,POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA 为捆绑提供动态加载。我们在这里标记了这个问题

https://github.com/webpack/webpack/issues/4716

要解决这个问题,我的队友找到了一个解决方法,使用babel插件去掉dev环境中的require.ensure。它将高级模块优化时间缩短为毫秒。随着工作的进行,我们的连续构建时间从8秒减少到1.5秒。

https://www.npmjs.com/package/babel-plugin-remove-webpack

答案 1 :(得分:1)

经过一些(更多)挖掘之后,我们最终得到了一个 hack 来欺骗webpack。 在我们的系统中,我们有许多异步加载的块和几个扩展的循环依赖,这导致很多块有很多父。 因此,主要耗时的任务是执行内置的 RemoveParentModulesPlugin 。 由于这个长模块链有很多块有很多父节点,所以这个插件还有额外的工作要做。

我们的解决方案是(仅在开发模式下)添加一个新的自定义插件,删除每个模块的父节点,因为我们在本地计算机上运行应用程序时不需要此优化。 / p>

这是我们的自定义插件的代码,以防有人在将来发现它有用:

function AvoidParentModulesOptimizationPlugin() {}
AvoidParentModulesOptimizationPlugin.prototype.apply = function(compiler) {
    compiler.plugin('compilation', function(compilation) {
        compilation.plugin(["optimize-chunks-basic", "optimize-extracted-chunks-basic"], function(chunks) {
            // We cheat webpack to think there are no parents to optimize
            // so recompilation time is quite low on development mode
            chunks.forEach(function(chunk) {
                chunk.parents = [];
            });
        });
    });
};

答案 2 :(得分:1)

对于开发具有大量异步路由的大型应用程序的任何人,您可能需要 babel-plugin-dynamic-import-node 。您可以使用它来将导入转换为开发模式中的需求。这样,块图非常快,我的构建时间从约30秒增加到了3秒。