首页 文章

如何配置webpack 4以防止出现在任何其他捆绑包中的入口点列表中的块?

提问于
浏览
23

我正在开展一个大项目并试图登陆webpack 3 - > 4更新 . 这个应用程序有大约1,000个入口点,其中大约10个被认为是“全局”或“核心”,并保证在每个页面上 . 这些核心包包含供应商和非供应商代码的混合 . 我需要配置webpack来构建所有这些资产,以便任何这些捆绑包中出现的任何块都不会出现在任何其他捆绑包中,无论块的大小如何,而无需创建需要添加到页面的新资产 .

使用webpack 3,我们一直在使用CommonsChunkPlugin来实现这一目标 . 这是一个简单的例子:

new webpack.optimize.CommonsChunkPlugin({
  name: 'a-global-bundle',
  minChunks: Infinity,
}),

现在有了webpack 4并删除了CommonsChunkPlugin,我不清楚如何完成这种优化 .

我'd like to be able to give webpack a list of entry points and any chunks that appear in any of those will not appear in any other bundle, but I'我不知道该怎么做 . 我已阅读some forthcoming documentation on splitChunks但我无法拼凑出一个解决方案 .

我已经设置了一个小型仓库作为修补的起点:https://github.com/lencioni/webpack-splitchunks-playground

我正在尝试的一个有趣的方向是为每个入口点配置一个 cacheGroups 组,并使用执行此检查的函数实现 test 选项 . 但是,文档在这方面相当稀疏,所以我不确定编写此测试函数的正确方法是什么,或者即使这样也可以 .

3 回答

  • 3

    您当前的配置(使用Webpack 3)使用 CommonsChunkPlugin 作为Explicit vendor chunk

    将代码拆分为供应商和应用程序 .

    检查repo的Webpack输出我发现 a.bundle.js 包含以下代码:

    // `react`, `react-dom` plus
    console.log('core module');     // from core-module.js
    console.log('core module b');   // from core-module-b.js
    console.log('non-core module'); // from non-core-module.js
    

    类似的代码在 b.bundle.js 中(此脚本中的差异是从 non-core-module-b.jsconsole.log('non-core module b'); 引用的最后一个 console.log ) .

    webpack.config.js 优化选项更新为:

    optimization: {
        runtimeChunk: 'single',
    
        splitChunks: {
            chunks: 'all',
    
            cacheGroups: {
                default: {
                    enforce: true,
                    priority: 1
                },
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    priority: 2,
                    name: 'vendors',
                    enforce: true,
                    chunks: 'all'
                }
            }
        }
    }
    

    在捆绑包之间生成非重复代码 .


    您可以检查工作代码here . 我还为你的示例项目创建了一个pull request .

    有关更多信息code splitting and the splitChunks optimization

  • 11

    好的,所以我想我已经想出了如何做到这一点 . 但首先,这是使用默认的splitChunks配置构建的内容(注意FOO.bundle.js是由动态导入创建的异步包):

    Asset       Size  Chunks                    Chunk Names
       core.bundle.js    605 KiB       0  [emitted]  [big]  core
      coreB.bundle.js    791 KiB       1  [emitted]  [big]  coreB
      coreC.bundle.js    791 KiB       2  [emitted]  [big]  coreC
          a.bundle.js    748 KiB       3  [emitted]  [big]  a
          b.bundle.js    792 KiB       4  [emitted]  [big]  b
          c.bundle.js    674 KiB       5  [emitted]  [big]  c
        FOO.bundle.js  709 bytes       6  [emitted]         FOO
    runtime.bundle.js   7.49 KiB       7  [emitted]         runtime
    

    如果目标是使核心,coreB和coreC中出现的任何模块不会出现在任何其他包中,则可以使用以下配置来完成:

    function coreBundleCacheGroups(coreBundles) {
      const cacheGroups = {};
      const coreChunkNames = Object.keys(coreBundles);
      const coreChunkNamesSet = new Set(coreChunkNames);
    
    
      coreChunkNames.forEach((name) => {
        cacheGroups[name] = {
          name,
          chunks: 'all',
          minSize: 0,
          minChunks: 1,
          reuseExistingChunk: true,
          priority: 10000,
          enforce: true,
          test(module, chunks) {
            if (module.depth === 0) {
              return false;
            }
    
            // Find first core chunk name that matches
            const partOfGlobalChunks = chunks.filter(chunk => coreChunkNamesSet.has(chunk.name));
    
            if (!partOfGlobalChunks.length) {
              return false;
            }
    
            const partOfGlobalChunksSet = new Set(partOfGlobalChunks.map(chunk => chunk.name));
            const firstCoreChunkName = coreChunkNames.find(name => partOfGlobalChunksSet.has(name));
            return firstCoreChunkName === name;
          },
        };
      });
    
      return cacheGroups;
    }
    
    const coreBundles = {
      core: './src/bundles/core.js',
      coreB: './src/bundles/core-b.js',
      coreC: './src/bundles/core-c.js',
    };
    
    module.exports = {
      mode: 'none',
    
      entry: {
        ...coreBundles,
        a: './src/bundles/a.js',
        b: './src/bundles/b.js',
        c: './src/bundles/c.js',
      },
    
      output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
      },
    
      optimization: {
        runtimeChunk: 'single',
    
        splitChunks: {
          cacheGroups: {
            ...coreBundleCacheGroups(coreBundles),
          },
        },
      },
    };
    

    产生以下输出:

    Asset       Size  Chunks                    Chunk Names
       core.bundle.js    605 KiB       0  [emitted]  [big]  core
      coreB.bundle.js    188 KiB       1  [emitted]         coreB
      coreC.bundle.js    1.5 KiB       2  [emitted]         coreC
          a.bundle.js   76.4 KiB       3  [emitted]         a
          b.bundle.js   2.28 KiB       4  [emitted]         b
          c.bundle.js   1.91 KiB       5  [emitted]         c
        FOO.bundle.js  622 bytes       6  [emitted]         FOO
    runtime.bundle.js   7.49 KiB       7  [emitted]         runtime
    
  • 1

    我们的目标是配置webpack以构建我们的资产,以便任何这些捆绑包中出现的任何块都不会出现在任何其他捆绑包中 .

    我之前有什么:

    new webpack.optimize.CommonsChunkPlugin({
                    name: 'vendor',
                    minChunks: function (module, count) {
                        // this assumes your vendor imports exist in the node_modules directory and module should be required
                        // in at least 3 entries before it moved to common chunk
                        return (module.context && module.context.indexOf('node_modules') !== -1) && count > 2;
                    }
                }),
    

    它现在如何运作:

    optimization: {
                splitChunks: {
                    cacheGroups: {
                        vendor: {
                            test: /[\\/]node_modules[\\/]/,
                            chunks: 'all',
                            name: 'vendor',
                            enforce: true,
                            minChunks: 3
                        }
                    }
                }
            },
    

相关问题