Home > Enterprise >  Webpack doesn't split a huge vendor file when modules are exported and imported using index fil
Webpack doesn't split a huge vendor file when modules are exported and imported using index fil

Time:11-18

Following Current Webpack Situation

It looks like the first place where one of the files is imported (let's say App.tsx) is where all the libraries get loaded, even if only one should be imported (in my intentions).

I want to add that this is happening even it the components that use the libraries are loaded dynamically, through React Suspense:

Sample from App.tsx
const PackagingComponent = lazy(
    () => import('src/components/PackagingComponent' /* webpackChunkName: "packaging" */)
);

And then

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

Solution?

If I remove the export in the index files (there are two in the project, one for common scripts and the other for hooks) and import the modules directly, the issue will go away.

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

You can see that the issue seems to be solved:

Possible solution

So I’m asking two things:

  1. Does anyone know why is this happening?
  2. Is there a more convenient way of exposing modules (without adding a new line for every new import)?

I thought that maybe I could put all the modules that import large libraries in a separate folder where I don’t export them with an index file, while keeping smaller modules in some common folders where I do export them using the index file, but I don’t like the solution as it doesn't feel consistent, and a co-worker which is not aware may take the issue back.

For context I also add the Webpack Split Chunks configuration:

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

(BTW the same happens if name is set to false).

CodePudding user response:

So, after posting the question, I've found this other question in the related section: Barrel file and Tree Shaking, which made me understand that the index files that I'm referring to have a name, which is barrel files, and that there are various articles on the subject.

This article for example advises not to use barrel files as they create issues with tree-shaking.

Luckily I've found this Github issue (in the Next.js repository) with the solution to my specific problem.

The solution is to turn off side effects for the barrel files, so that Webpack will not load the whole folder every time you need one single module.

So in my case the relevant part of the Webpack configuration becomes:

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

Everything else stays the same.

Finally I would like to quote a part of this reply from the same user which gave the solution:

Barrel files are effectively an API. A specific interface that distinguishes private vs public code. It especially makes sense in a monorepo with local packages. The same concept (why do packages have a specific import interface) pros/cons applies to monorepo packages.

So in the end I'm thankful that I've been able to keep barrel files without having to import every module separately.

  • Related