DEV Community

AK DevCraft
AK DevCraft

Posted on • Updated on

Barrel - Best Way to Import Files in Modern JavaScript Apps

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.

Wild wild import
wild import

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
little very wild import

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

ok ok import

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.
way better import

Auto import suggestion simplified.
auto import suggestion

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.
best

If we import file as something, then this is how can be used.
import as usage

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.

Project Structure:
proj str

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
data level

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
util level

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
comp level

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.

Agent level

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

tp level

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,
      }
    ]
Enter fullscreen mode Exit fullscreen mode

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.

My Other Blogs:

Top comments (4)

Collapse
 
smitterhane profile image
Smitter

Though the problem with barrels is that there is no tree-shaking support when using bundlers like webpack, parcel, rollup...

Collapse
 
akdevcraft profile image
AK DevCraft • Edited

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).

rules: [
      {
        test: [/src\/components\/index.ts/i],
        sideEffects: false,
      }
    ]
Enter fullscreen mode Exit fullscreen mode
Collapse
 
adamquadmon profile image
Luciano Amodio

Better to start the article with the tree shaking warning

Collapse
 
akdevcraft profile image
AK DevCraft

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.