javascript Webpack在使用桶文件时不会拆分巨大的供应商包

iyfjxgzm  于 2023-05-12  发布在  Java
关注(0)|答案(1)|浏览(123)

this answer之后的问题Is it possible to import modules from all files in a directory, using a wildcard?中,我能够在一个声明中导入多个模块,并像这样导出它们:

/hooks/index.ts部分
export { default as useSections } from './useSections';
export { default as useArtworkEvents } from './useArtworkEvents';
export { default as useEventBusListener } from './useEventBusListener';

然后将它们导入到一个组件中,如下所示:

Packaging.tsx部分
import { useSections, useArtworkEvents, useEventBusListener } from 'src/hooks';

我在另一个没有问题的项目中做了同样的事情,但是这里我从模块中导入了大型库,所有这些库都进入了vendor文件夹。
库的导入方式如下:

其中一个钩子的示例
import { autorun, IReactionDisposer } from 'mobx';
// body of the module
// and the export in the end
export default useArtworkEvents;

而这就是目前的情况:

它看起来像是导入其中一个文件的第一个地方(假设是App.tsx)是加载所有库的地方,即使只有一个应该被导入(在我的意图中)。
我想补充的是,即使使用库的组件是通过React Suspense动态加载的,这种情况也会发生:

示例来自App.tsx
const PackagingComponent = lazy(
    () => import('src/components/PackagingComponent' /* webpackChunkName: "packaging" */)
);

然后呢

<ErrorBoundary locale={props.locale}>
  <Suspense fallback={<Loader />}>
    {props.componentType === AcceptedComponentTypes.PACKAGING && (
      <DesignStackPackaging
        locale={props.locale}
        tenant={props.tenant}
      />
     )}
     {/* ...other conditions */}
  </Suspense>
</ErrorBoundary>

解决方案?

如果我删除索引文件中的导出(项目中有两个,一个用于普通脚本,另一个用于钩子)并直接导入模块,问题就会消失。

/hooks/index.ts部分
export {};
Packaging.tsx部分
import useSections from 'src/hooks/useSections';
import useArtworkEvents from 'src/hooks/useArtworkEvents';
import useEventBusListener from 'src/hooks/useEventBusListener';

你可以看到这个问题似乎已经解决了:

所以我有两个要求
1.有人知道为什么会这样吗?
1.有没有更方便的方法来公开模块(而不用为每个新导入添加新行)?
我想也许我可以把所有导入大型库的模块放在一个单独的文件夹中,在那里我不使用索引文件导出它们,同时将较小的模块保存在一些常用的文件夹中,在那里我使用索引文件导出它们,但我不喜欢这个解决方案,因为它感觉不一致,并且不知道的同事可能会收回这个问题。
对于上下文,我还添加了Webpack Split Chunks配置:

splitChunks: {
  chunks: 'all',
  name: true,
},

(BTW如果name被设置为false,则发生相同的情况)。

wfsdck30

wfsdck301#

所以,在发布问题后,我在相关部分找到了另一个问题:Barrel file and Tree Shaking,这让我明白了我所指的index文件有一个名称,即桶文件,并且有各种关于该主题的文章。
例如,This article建议不要使用桶文件,因为它们会产生树抖动问题。
幸运的是,我找到了this Github issue(在Next.js存储库中),其中包含我的特定问题的解决方案。
解决方法是关闭桶文件的副作用,这样Webpack就不会在每次需要单个模块时加载整个文件夹。
因此,在我的例子中,Webpack配置的相关部分变为:

{
  module: {
    rules: [
      // other rules...
      {
        test: [/src\/common\/index.ts/i, /src\/hooks\/index.ts/i],
        sideEffects: false,
      }
    ]
  }
}

其他一切都保持不变。
最后,我想引用同一个用户的一部分回复,给出了解决方案:
Barrel文件实际上是一个API。区分私有代码和公共代码的特定接口。这在带有本地包的monorepo中尤其有意义。同样的概念(为什么包有一个特定的导入接口)利弊适用于monorepo包。
所以最后我很感激我能够保留桶文件,而不必单独导入每个模块。

相关问题