Introduction
Lets face this, everyone of us must have seen imports like this import { DataFormatter } from './components/utils/data-formatter/data-formatter';
and most likely did use import in similar style. However, I know for sure it was not intentional and not intended to make peers' life difficult. It was probably because we didn't know about barrel files. In this tutorial, I will talk about barrel files along with demo and how it can simplify our lives as simple as a simple file import. Just practical not theoretical!
Barrel is not just about making file import pretty, but it helps us to keep the code base clean and maintainable.
Benefits
Using barrel files we can go from import like import { DataFormatter } from './components/utils/data-formatter/data-formatter';
style, to import like import { DataFormatter } from './components';
. We’ll be taking small steps and improving as we go through this tutorial.
Level one export - export just from component module
Exporting only from respective file module
With exporting from same module, we reduced the lengthy export a bit i.e. from import { DataFormatter } from './components/utils/data-formatter/data-formatter';
to import { DataFormatter } from './components/utils/data-formatter';
. Notice last part data-formatter is not needed anymore.
Level two export - export from parent module
Export from outer module as well
Now exporting from parent module, we further reduced the lengthy export a little more i.e. from import { DataFormatter } from './components/utils/data-formatter';
to import { DataFormatter } from './components/utils';
. Notice second data-formatter is also not needed anymore.
But no need to stop now. Let’s go further and import file from a module instead of long painful import statement.
Level three export - combine different exports
Combine multiple exports as single
Well! way to go import { Accordion, Button, DataAnalytics, DataFormatter } from './components';
, how about this? doesn't it like simple when compared first import style import { DataFormatter } from './components/utils/data-formatter/data-formatter';
. We travelled a long way just like humans trying to travel across the galaxy.
Auto import suggestion simplified.
Level three export with as keyword
No need to write multiple file name in the import directly use the file in the code.
We can even go one level removing file name from the import import * as component from './components';
, though in my opinion is a good way to import when to many file imports are need but I guess I'll leave this to developer perspective.
If we import file as something, then this is how can be used.
Demo
Alright! showtime, enough of bragging (Time to test the waters). Below is the project structure which I'll be using for this tutorials. App.tsx
file is under src
module, src
module is under project module i.e. barrel-example
. third-party
module is parallel to src i.e. directly under root project barrel-example
directory.
If you just want to simplify the import as level one export, just use this.
Create index.tsx
for typescript project (based upon your project type create .jsx
or .js
) for the component under path ./barrel-example/src/components/utils/data-analytics/index.tsx
If you're little more curious and committed then re-export from its parent directory Level two export.
Again create another index.tsx
for typescript project (based upon your project type create .jsx
or .js
) that will provide level two export ./barrel-example/src/components/utils/index.tsx
If you want the best, then obvisouly you won't stop and go for Level three export.
Create index.tsx
for typescript project (based upon your project type create .jsx
or .js
) that will provide level three export ./barrel-example/src/components/index.tsx
Other way to export in case file are not directly inside the src
module.
Parallel to src module directly under root directory, as it was done previously create index.tsx
for typescript project (based upon your project type create .jsx
or .js
) that will provide Level one export, ./barrel-example/third-party/agent/index.tsx
, re-export default exported file to name export file.
Note - No need to change default to name export in the actual file. Just use
default as Agent
or whatever is the file/component name.
Kind of both level two and three export.
Parallel module, level two/three export create index.tsx
for typescript project (based upon your project type create .jsx
or .js
), ./barrel-example/third-party/index.tsx
Caution
Barrel file have known issue when it comes for tree shaking with module bundlers like webpack, rollup etc. Below workaround would work for webpack. In my opinion, applications that are extended as external library may not be good use case for the barrel files, better use case will be single page apps where it'll be easier to eliminate dead code (ultimately making it less rely on tree shaking)
rules: [
// some other rules..
{
test: [/src\/components\/index.ts/i],
sideEffects: false,
}
]
And that's it! Here is the link to my GitHub project, explore yourself.
If you have reached here, then I made a satisfactory effort to keep you reading. Please be kind enough to leave any comments or ask for any corrections.
Top comments (4)
Though the problem with barrels is that there is no tree-shaking support when using bundlers like webpack, parcel, rollup...
Yeah, that's true, but I guess below workaround would work for webpack. I guess, not really recommended for the applications that are extended as library, better use case will be single page applications (where easier to eliminate dead code).
Better to start the article with the tree shaking warning
I was kind of debating myself whether tree shaking warning should be in the beginning, but as we human see more obstacles then the path ahead, I left the caution section in the end so that whoever reads it take informed decision rather seeing the challenges first and unintentionally not go in the details.