The clean index.ts file you were told to create? It's actually causing tree-shaking to fail silently. Do you know that kind of import that just re-exports everything from the folder so your import looks great? Well, that good practice actually can be a bundle-size footgun. ## What a barrel file actually is
A barrel file refers to the index.ts file that gathers and re-exports multiple modules.
export * from './Button'
export * from './Modal'
export * from './Tooltip'
plaintext
Now you import one thing from '@/components' and feel organized. It feels awesome. The issue here is that your bundler must be able to understand the entirety of that barrel in order to determine what you are actually using. If tree-shaking is unable to clearly eliminate the rest, that's what gets sent along. ## The receipts are brutal
It's not just a feeling. Scientists have quantified it. Bartosz Łaniewski performed this test in April 2024. When he imported a Material-UI component via a barrel file, he received a bundle of approximately 151 kB. However, after making a direct import, the bundle was only around 75 kB. It's the exact same component but the bundle was half the size. In July 2024, Dominik Dorfmeister, React Query maintainer, and his team found that their Next.js pages were loading over 11k modules, starting in 5 to 10 seconds. After ripping out internal barrel files, they loaded to roughly 3.5k modules. That's a 68% cut. And the cycle continues:
→ A dev shaved production first-load JS from 1.5 MB to 200 KB, an 85% drop, by switching to direct imports (Medium, May 2025)
→ CatchMetrics cut a client's bundle by 400 KB by killing a single barrel that re-exported a pile of SVGs
→ Reactuse.com's August 2025 deep-dive ties barrel files directly to broken tree-shaking and circular dependencies
Even the tools are begging you to stop
If the bundler documentation gives you a heads-up, it's wise to take it seriously. On the official Vite documentation, "Avoid Barrel Files" is listed right after Performance tuning. The reasoning behind it is simple: you import one API, and every file the barrel has is fetched and transformed. It's a slower page load, guaranteed. The team at Vercel was also aware of this issue. In October 2023, with Next.js 13.5, engineer Shu Ding shipped optimizePackageImports specifically to neutralize third-party barrel files. This improved local dev startup by 15% to 70%. I remember the @material-ui/icons number. Dev startup went from 10.2 seconds down to 2.9 seconds. An entire compiler feature to babysit a "best practice". The SDK generator, Speakeasy, allows you to disable the barrel file generation because according to them it gives you "Superior tree shaking performance" and "faster build performance" by removing those intermediary import chains. ## So it's a bundler bug, right? I can already imagine the excuses. Somewhat. Yet not quite. A convention that needs a dedicated compiler flag, a Vite warning, and an SDK opt-out to behave is not a neutral convention. It's a footgun with safety features bolted on after the fact. What's really uncomfortable is that we sent this to junior devs with clean code, sorted imports, and neat folders; without telling them that it can drag your dev server to its knees and double your bundle. ## What I actually do now
How about importing directly from the source file? Sounds dull but is amazingly fast!
import { Button } from '@/components/Button'
Here are a few rules that I always remember:
→ Direct imports for anything perf-sensitive, especially in a Next.js app
→ Turn on optimizePackageImports for the third-party barrels you can't control
→ If a barrel exists purely to make an import path prettier, delete it
→ Watch for circular deps, barrels love to create them quietly
Clean code should make your life easier. When the cleanest pattern is the one that sets your build times on fire, the aesthetics lied to you. 🔥
Here's the real question: Is the barrel file a design flaw that persists to this day, or just a bundler that never managed to stay caught up? Which side of the barrel are you on?
Top comments (0)