代码之家  ›  专栏  ›  技术社区  ›  Joe Lencioni

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

  •  30
  • Joe Lencioni  · 技术社区  · 7 年前

    我正在从事一个大型项目,并试图获得网页3->4更新。这个应用程序大约有1000个入口点,其中大约10个被认为是“全球”或“核心”,保证出现在每个页面上。这些核心捆绑包包含供应商和非供应商代码的混合。我需要配置webpack来构建所有这些资产,以便在不创建需要添加到页面的新资产的情况下,出现在这些捆绑包中的任何块都不会出现在任何其他捆绑包中,而不管块的大小如何。

    在webpack 3中,我们一直在使用CommonChunkPlugin来实现这一点。下面是一个简单的示例:

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

    现在,随着Webpack4和CommonChunkPlugin的删除,我不清楚如何完成这种优化。

    我希望能够给webpack一个入口点列表,任何出现在其中的块都不会出现在任何其他包中,但我不知道如何做到这一点。我已经通读了 some forthcoming documentation on splitChunks 但我还没能拼凑出一个解决方案。

    我已经建立了一个小型回购协议,作为修补的起点: https://github.com/lencioni/webpack-splitchunks-playground

    我正在尝试的一个有趣的方向是配置 cacheGroups 每个入口点都有一个组,并实现 test 具有执行此检查的函数的选项。然而,关于这方面的文档非常少,因此我不确定编写此测试函数的正确方法是什么,甚至不确定这是否可行。

    3 回复  |  直到 7 年前
        1
  •  12
  •   smac89    7 年前

    好的,我想我已经知道怎么做了。但首先,以下是默认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
    

    如果目标是使出现在core、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
    
        2
  •  3
  •   Carloluis    7 年前

    您当前的配置(使用Webpack 3)使用 CommonsChunkPlugin 对于 Explicit vendor chunk :

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

    正在检查您的 repo 我发现了 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 (此脚本中的差异是最后一个 console.log 引用自 non-core-module-b.js : console.log('non-core module b'); )。

    更新 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

        3
  •  1
  •   WelcomeTo    7 年前

    我们的目标是配置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
                        }
                    }
                }
            },
    
    推荐文章