【问题标题】:Code-splitting separate exports from a package to different bundles将包中的代码拆分单独导出到不同的包
【发布时间】:2020-06-04 18:34:47
【问题描述】:

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

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

如果感觉应该可以将 @example/forms 中的各个组件拆分为特定于页面的捆绑包,但我不确定我是否希望太多。例如,如果表格 A 仅用于第 4 页,我希望表格 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,然后将剩下的拆分成 bundle。使用该逻辑,@example/forms 将在多个页面上使用,并将被移至公共区域。然而,这绝对不是最佳的,希望不是正在发生的事情。

【问题讨论】:

  • 可以将功能/组件拆分为特定的块,但您想要的结果是什么?我知道如何手动制作,你可以吗?
  • 您也可以使用dynamic importsReact.lazy 让您的表单延迟加载,当然也可以打包到自己的包中。检查反应Code-Splitting

标签: javascript webpack bundle gatsby tree-shaking


【解决方案1】:

Tree-shaking 过程是真正处于后期阶段的缩小步骤的一部分,因为不可能颠倒顺序,首先 tree-shake 然后块拆分。

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

  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 模块中的每个表单创建一个块,在我的示例中,我根据表单路径“分组”所有项目。
// 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

希望对你有帮助

【讨论】:

  • 这个答案对你有帮助吗?
猜你喜欢
  • 2017-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 2020-03-13
  • 1970-01-01
  • 2017-11-24
相关资源
最近更新 更多