javascript - 将包中的代码拆分单独导出到不同的包

标签 javascript webpack bundle gatsby tree-shaking

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

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

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

这是支持的东西吗?如果支持,是什么阻止了这种情况的发生。
@example/forms与 ES6 导出保持原样进行转译,并且 sideEffects设置为 false在其package.json .

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将在多个页面上使用,并将被移至公共(public)区域。然而,这绝对不是最佳的,希望不是正在发生的事情。

最佳答案

摇树过程是真正处于后期阶段的缩小步骤的一部分,因为不可能颠倒顺序,首先摇树然后分 block 。

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

  • 最基本的是使用splitChunks为了分割这个@example/forms模块作为一个整体分成一个单独的 block ,这将减少公共(public)膨胀&在第一个表单使用时,所有表单都将被加载。

  • // 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[\\\/]/,
            },
          },
        },
      },
      ...
    };
    
  • @example/forms 中的每个表单创建一个 block 基于一些启发式的模块,在我的示例中,我根据表单路径“分组”所有项目。

  • // 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

    希望这可以帮助

    关于javascript - 将包中的代码拆分单独导出到不同的包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62201836/

    相关文章:

    javascript - 如何生成最小尺寸的 Javascript 对象?

    javascript通过正则表达式提取日期

    node.js - Webpack:找不到模块:错误:无法解析模块 browser.js

    ios - 无法更改项目中的包 ID,灰显

    c# - 如何在 MVC5 中为 Bundle 启用缓存

    下一个元素的Javascript dom选择

    javascript - Twitter Bootstrap - selectpicker 在通过 JS 添加它们后没有反应

    javascript - Webpack - scss/css 模块样式未在产品中应用

    javascript - 错误: No ErrorHandler. 是否包含平台模块(BrowserModule)?尝试从 jsf 页面加载 Angular 应用程序时

    java - Gradle Jar - 包括依赖项的类