Barrel file and Tree Shaking
Asked Answered
P

2

28

Here is an example repository that shows an example of the issue reported in this thread: https://github.com/Eux86/tree-shaking-barrel-test/blob/master/README.md

I'm trying to understand what's the effect of using a Barrel file to export functions and classes from a library project when importing it into another project that use webpack and should be able to treeshake the bundle.

Imagine I have a project:

library

  • index.ts

  • libA.ts

  • libB.ts

index.ts has this code:

export { LibAMain } from 'LibA';
export { LibBMain } from 'LibB';

So I'm using index as a barrel file to export all the functions I'm going to develop in my library.

The second project will be:

library-user

  • index.ts

Index.ts has this code:

import { LibAMain } from 'library'

LibAMain();

Now: library-user is builded using webpack, which I expect to be able to treeshake the unused libraries in MyLib, but when I look into the generated bundle I see that it contains both LibA.js and LibB.js, which shouldn't be there:

enter image description here

If I change index.ts to:

import { LibAMain } from 'library/lib/LibA'

LibAMain();

then webpack does its job well and I only see LibA in the final bundle:

enter image description here

TL;DR: How can I keep using the barrel index file and just import everything from 'library' but still have the treeshaking working?

Thank you for any help :)

Pennyroyal answered 23/10, 2019 at 17:12 Comment(1)
Possibly the same issue I'm experiencing here? #74443196Beatrix
D
21

It looks like a module problem in your code, not webpack.
tsconfig.json

...
"module": "commonjs",
...

Commonjs modules system doesn't support tree shaking in webpack (only direct imports like you did it above works mylib/libA).
To fix tree shaking in your github repo you should use module: es2015 or esnext in tsconfig.json.

...
"module": "esnext",
...

But you are right - unfortunetely treeshaking is not webpack's best side.
There are several approaches how to shake your tree better:

  1. Plugin to improve treeshaking
  2. Side effects webpack option
  3. Used exports webpack option
  4. Move from webpack to rollup. Rollup has first-class tree shaking by default (I don't recommend to do it for large projects).
Dangle answered 16/12, 2019 at 8:49 Comment(1)
Why you don't recommend Rollup for large projects?Premier
B
5

By looking for an answer to my own question Webpack doesn't split a huge vendor bundle when using barrel files I've found a solution that should apply in this case as well.

Basically you can continue to use barrel files, but you need to disable side effects from those specific files (the barrel files).

I've tried this solution in two separate projects with different versions of Webpack (4 and 5) and it works on both.

This is the relevant part of the configuration:

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

Here is a link to the GitHub issue where I've found the explanation: https://github.com/vercel/next.js/issues/12557.

Beatrix answered 17/11, 2022 at 17:8 Comment(1)
More details in this article: renatopozzi.me/articles/your-nextjs-bundle-will-thank-youBeatrix

© 2022 - 2024 — McMap. All rights reserved.