代码拆分将一个包的导出单独导出到不同的包

Code-splitting separate exports from a package to different bundles

我有一个使用大量包的 Gatsby 站点。其中一个软件包是从我们的 monorepo 发布的:@example/forms。该包包含许多命名的导出,一个用于我们网站上使用的每个表单组件。有相当多的形式,有些是相对复杂的多步形式,规模不小。

目前,Gatsby/Webpack 在 treeshaking 方面做得很好,并且确实产生了大量的 bundle,一些公共 bundle 和一个用于站点的每个页面,包含任何本地资产或仅使用的组件在那个页面上。但是,@example/forms 中的所有组件都被添加到 commons 包中,尽管大多数组件仅在一个页面上使用。这导致在每个页面上加载的 commons 包不必要的膨胀。

如果感觉 @example/forms 中的各个组件应该可以拆分成特定于页面的包,但我不确定我是否希望太多。例如,如果仅在第 4 页使用表格 A,我希望仅将表格 A 添加到第 4 页的捆绑包中。

这是受支持的东西吗?如果是,是什么阻止了这种情况的发生。

@example/forms 被转译,ES6 导出保持不变,sideEffects 在其 package.json 中设置为 false

它的 main 文件是 index.js,它从它们自己的文件中(重新)导出所有表单组件作为单独的命名导出:

export {default as FormA} from './forms/formA'
export {default as FormB} from './forms/formB'
...

另一件可能相关的事情是,所有来自 @example/forms 的导出都是 在 Gatsby 站点中使用的,只是在单独的页面上。看起来 tree-shaking 可能不能跨束使用,即首先执行 tree shaking,然后将剩下的分成束。使用该逻辑,@example/forms 将在多个页面上使用并移至公共区域。然而,这绝对不是最优的,希望不是正在发生的事情。

tree-shaking 过程是缩小步骤的一部分,实际上处于后期阶段,因为不可能颠倒顺序,先 tree-shaking 然后分块。

但是您可以使用一些启发式方法事先拆分您的表单库

  1. 基本的方法是使用 splitChunks 将这个 @example/forms 模块拆分成一个单独的块作为一个整体,这将减少公用膨胀 & 在第一种形式上使用所有形式已加载。
// webpack.config.js

module.exports = {
  ...
  optimization: {
    splitChunks: {
      cacheGroups: {
        formComponents: {
          chunks: 'all',
          enforce: true,
          minChunks: 1,
          name: 'form-components',
          priority: 10,
          test: /[\\/]node_modules[\\/]@example[\\/]forms[\\/]/,
        },
      },
    },
  },
  ...
};
  1. 根据一些启发式方法为 @example/forms 模块中的每个表单创建一个块,在我的示例中,我 "grouping" 所有项目都基于表单路径。
// webpack.config.js

module.exports = {
  ...
  optimization: {
    splitChunks: {
      cacheGroups: {
        formComponents: {
          chunks: 'all',
          minChunks: 1,
          name(module) {
            const libPath = path.resolve(path.join('node_modules/@example/forms'))
            const folderBasedChunk = path.relative(libPath, module.context);
            const hash = crypto.createHash('sha1');
            hash.update(folderBasedChunk)
            return hash.digest('hex').substring(0, 8)
          },
          priority: 10,
          reuseExistingChunk: true,
          enforce: true,
          test: /[\\/]node_modules[\\/]@example[\\/]forms[\\/]src[\\/]forms[\\/]/,
        },
      },
    },
  ...
};

您可以查看我创建的模拟场景的小示例。 https://github.com/felixmosh/webpack-module-split-example

希望对您有所帮助