Skip to content
Architecture Lab · LAB-09barrel files / tree shaking

What does a barrel file cost?

One tidy index.ts, one import, and suddenly the route bundle contains a charting library nobody on that page uses.

Level
SYSTEMS
Read time
08 min
Experiment
Available
Type
INVESTIGATION

The question

Why does importing a single helper from a barrel file sometimes pull in an entire package, and why does tree shaking not save you?

Hypothesis

A barrel re-exports every module in a directory. Unless every one of those modules is provably free of side effects, the bundler must keep them.

Method

Laboratory available

The instrument for this investigation runs in the laboratory, where the controls, the live model and the observation log share one workstation.

Enter the laboratory

Add packages to the graph and watch the transitive closure and the shipped estimate move. The same mechanics apply inside your own source tree.

What we observed

components/index.tsts
export * from "./Button";export * from "./Chart";        // pulls in the charting libraryexport * from "./DatePicker";   // pulls in the date libraryexport * from "./Table";
The convenient version

Importing Button from that barrel asks the bundler to evaluate the whole module graph behind it. With clean ESM and no side effects it can drop the unused branches. One sideEffects omission, one CommonJS dependency or one module-scope registration is enough to keep everything.

Why it happens

What keeps a module alive

  1. 01The package does not declare "sideEffects": false, so the bundler must assume importing it does something observable.
  2. 02A module runs code at import time: registering a web component, polyfilling, mutating a prototype, reading configuration.
  3. 03The dependency is CommonJS, so its exports cannot be analysed statically.
  4. 04A namespace import is indexed dynamically, which defeats static analysis.

The fix is boring: import from the module, not from the directory. Keep barrels for genuinely small, side-effect-free groups, and let the build measure the difference rather than trusting that tree shaking will handle it.

Further research

Check the claim rather than the convention. A bundle analyser will tell you which modules a route actually contains, and comparing two builds, one importing through the barrel and one importing directly, settles the argument in about ten minutes.

References

  1. 01MDNTree shaking
  2. 02webpacksideEffects
  3. 03Node.jsPackage entry points