I use barrel files to expose a small API for each domain and lint rules to discourage deep imports. Code inside a domain imports its own modules directly. Is this likely to hurt tree shaking, and is there a better way to define those boundaries without turning everything into packages?
Are barrel files a problem for tree shaking when defining internal boundaries?
Answers
A barrel isn't automatically a bundle-size problem. Modern bundlers can often remove unused exports, but the result depends on the module graph, side effects, and the tool's configuration. A module that does work at the top level may still need to be included even if its exports aren't used.
Named re-exports can make the public API easier to inspect. Wildcard exports aren't necessarily impossible to shake, but they can make the graph harder to reason about. Keeping internal imports away from the domain's own barrel also helps avoid introducing circular dependencies through that entry point.
Reply to this answer
Measure it in your actual build. Pick a representative barrel, replace its use with direct imports in a test branch, and compare the production bundle and build time. Check the bundler's output or bundle analysis to see which modules remain and why.
One comparison won't prove every barrel is fine, but it'll give you a more useful starting point than a blanket rule.
Reply to this answer
If the boundary is valuable, keep the barrel and lint rule. They serve a different purpose from tree shaking: making cross-domain dependencies visible and giving each domain a deliberate public surface.
That is still a convention enforced by tooling, though. Without the rule, someone can generally reach around the barrel with a deep import.
Reply to this answer
Workspace packages with package.json exports are another option. The exports map defines the package entry points and can prevent consumers from importing unexported package paths through normal package resolution.
That's a stronger package boundary, but it comes with package management overhead. It also doesn't magically fix tree shaking or side effects, so I wouldn't restructure solely on that assumption.
Reply to this answer
There's also a reasonable case for fewer boundaries. If a domain's public API isn't giving the team much value, direct imports may be simpler than maintaining a barrel and custom rules. That choice depends on how much coupling you're trying to control, not just bundle size.
Reply to this answer
Add your answer
Answers are reviewed before publication.
c28!busphase_740:
Build time is a separate consideration too. A bundler may still need to inspect modules that don't end up in the final bundle.