代码拆分从包到不同包的单独导出

Und*_*ion 11 javascript bundle webpack gatsby tree-shaking

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

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

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

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

@example/forms被transpiled与ES6出口保持不变,并sideEffects设置为false在其package.json

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

export {default as FormA} from './forms/formA'
export {default as FormB} from './forms/formB'
...
Run Code Online (Sandbox Code Playgroud)

这可能是相关的另一件事是,全部来自出口@example/forms 盖茨比网站内使用,只是在不同的页面。看起来也许 tree-shaking 不能跨 bundle 使用,即首先执行 tree-shaking,然后将剩下的拆分成 bundle。使用该逻辑,@example/forms将在多个页面上使用并移至公共区域。然而,这绝对不是最佳的,希望不是正在发生的事情。

fel*_*osh 4

树摇动过程是缩小步骤的一部分,实际上处于后期阶段,因为不可能颠倒顺序,首先进行树摇动,然后进行块分割。

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

  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[\\\/]/,
        },
      },
    },
  },
  ...
};
Run Code Online (Sandbox Code Playgroud)
  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[\\\/]/,
        },
      },
    },
  ...
};
Run Code Online (Sandbox Code Playgroud)

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

希望这可以帮助