Barrel Files - What? Why? How? ๐Ÿค”

Barrel Files - What? Why? How? ๐Ÿค”

ยท

5 min read

TLDR;

Barrel files are a single point of contact when the entire app needs any file. Create different barrel files for different categories (pages, components, utils, styles). They improve the developer experience by a stretch and make code cleaner.


What is a barrel file?

Before we go coding

Imagine you are the owner of a hotel in a hustling bustling tourist hot spot on the mountain. Your premium hotel can house more than a thousand guests at a time. Being on vacation, our guests love to order local cuisine from the online ordering app.

Off-topic - You know it's a good hotel when it has a pool and a coconut tree ๐Ÿ˜Ž

Numerous delivery partners come and go on a daily basis. When the food arrives, you need to send the correct order to the correct room. For this purpose, you have employed a receptionist waiting in the reception. He checks which parcel needs to be sent to which room and then directs the help to take the food to the requisite room. Notice two things-

  1. The receptionist has access to all the rooms (The ability to get the data from the room)

  2. The receptionist can send stuff to these rooms (The ability to send the room's data to the public)

We can think of barrel files like our mighty receptionist. The barrel file has access to other files to import modules and it also exports the modules from said files. In a scenario where any part of the app needs a module, it can reach out to the barrel file and ask for the file for its use.

The code way

A barrel file is a file that imports modules from other files and exports the said modules.

A barrel file in JavaScript is a way to group and export multiple modules from a single file. It allows for easier importing of the grouped modules by providing a centralized location to access them.

- How we optimized package imports in Next.js

Show me the code

// components/index.js => This is our barrel file for components

import Footer from './Footer.js'
import Header from './Header.js'
import UserCard from './UserCard.js'

export { Footer, Header, UserCard }
// pages/profile.js => Profile page using Footer, Header and UserCard

import { Footer, Header, UserCard } from '../components'

export default function Profile () {
    return (
        <>
            <Header />
            <UserCard />
            <Footer />
        <>
    )
}

See how beautiful and clean our code looks. ๐Ÿ˜‡

Why barrel file?

In case there is no receptionist and all the delivery partners start going to the rooms they need to go to. Imagine the chaos in the hallways. Our guests would have a bad experience

Similarly, not using barrel imports would lead to writing more lines of code. Take our code example, with one change that there is no barrel file. To access the components, we would need to directly import from their module file ultimately leading to two more extra lines.

// pages/profile.js => Without barrel file

import Footer from '../components/Footer.js'
import Header from '../components/Header.js'
import UserCard from '../components/UserCard.js'

export default function Profile () {
    return (
        <>
            <Header />
            <UserCard />
            <Footer />
        <>
    )
}

Three things to notice here -

  • Now, escalate this issue to a few hundred lines of imports. And you get the picture of how messy the code will look.

  • One more thing that is difficult to explain in a blog is when you are trying to figure out which module is coming from which file. Since the code is not so clean and shiny like a brand new Ferrari, reading the code asks for more effort from the dev's end, leading to a poor dev experience.

  • The imports may seem logical to the OG dev since they worked on the file folder structure, but for every next contributing dev, it's a headache.


Hold your horses ๐Ÿด

Before you start falling in love with the barrel exports (like I did for that girl in high school), there are a few caveats. While we talked about dev experience and cleaner code, we missed out on a very important part, the thing that tickles every dev's soul, PERFORMANCE. Since this is in all caps, it must be important. And it is.

Stay tuned for the next part in this mini-series (Barrel - The Good, the Bad and the Ugly). In the next part, we'll explore how the barrel exports impact our app's performance.


Bonus - since you read till the last ๐Ÿ™‡โ€โ™‚๏ธ

Take it from someone who has messed up implementing this simple barrel import and has spent hours trying to figure out what went haywire, just to find out there was an issue exporting from the barrel file; use this flow for implementing the barrel.

  • Step 1 => Create a module file

  • Step 2 => Export the module before coding the function

  • Step 3 => Import the module in the barrel file (Do not create the component yet)

  • Step 4 => Export the module in the barrel file

  • Step 5 => Start working on the component

I, on numerous occasions, have either forgotten to import and export from the barrel file while trying to use the barrel file in another part of the app OR have forgotten to export the module and kept wondering why the barrel file is unable to import the module. This way, I make sure never to face these two issues again.

Over to you

Do share and let me know in the comments how you found my way of explaining. Being a noob, I would really appreciate some criticism (good and bad) to work on my blogs.

Until next time, Ciao ๐Ÿ‘‹