Reputation: 512
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 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:
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:
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 :)
Upvotes: 31
Views: 13571
Reputation: 2059
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.
Upvotes: 7
Reputation: 6599
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:
webpack
to rollup
. Rollup has first-class tree shaking by default (I don't recommend to do it for large projects).Upvotes: 25