Intro
The magic phrase import x from "y" is one of the most common phrases in the day of a JavaScript developer. But sometimes, it is TOO common.
If you’re here, that means you’re probably tired of seeing something like this:
1import { Navbar } from "../components/Navbar"; // 1
2import { Container } from "../components/Container"; // 2
3import { Header } from "../components/Header"; // 3
4import Footer from "../components/Footer"; // 4
5// (╯°□°)╯︵ ┻━┻
6
7export default function HiMom() {
8 return (
9 <>
10 <Navbar />
11 <Container>
12 <Header title="Hi mom" />
13 {[...Array(4).keys()].map(i => (
14 <p key={i}>
15 Lorem ipsum dolor sit amet consectetur adipisicing elit. Soluta
16 exercitationem explicabo provident quisquam. Maxime tempora ipsum
17 debitis voluptas nulla fuga neque officiis.
18 </p>
19 ))}
20 </Container>
21 <Footer />
22 </>
23 );
24}
Well, fear not, because barrel exports have come for the rescue.
But what is a barrel exactly? A barrel is simply a file that re-exports the exports of other files, allowing you to import everything from it. This means that the above code could be refactored to this:
1import { Navbar, Container, Header, Footer } from "../components"; // 1
2// ヾ(^▽^*)))
3
4export default function HiMom() {
5 return (
6 <>
7 <Navbar />
8 <Container>
9 <Header title="Hi mom" />
10 {[...Array(4).keys()].map(i => (
11 <p key={i}>
12 Lorem ipsum dolor sit amet consectetur adipisicing elit. Soluta
13 exercitationem explicabo provident quisquam. Maxime tempora ipsum
14 debitis voluptas nulla fuga neque officiis.
15 </p>
16 ))}
17 </Container>
18 <Footer />
19 </>
20 );
21}
Woah! So how do I make a barrel?
Well, I’m glad you asked! Here is an example with a Next.js project, where we can find all of those files in the components folder.
Now, take a look in the index.js file in the components folder. This is our barrel module, which will re-export all other modules.
1export * from "./Navbar";
2export * from "./Container";
3export * from "./Header"; // For named exports
4export { default as Footer } from "./Footer"; // For default exports
If you’re using CommonJS, you can achieve the same result by importing the files first and then adding them in the module.exports.
1const { Layout } = require("./Layout");
2const { Container } = require("./Container");
3const { Header } = require("./Header"); // For named exports
4const Footer = require("./Footer"); // For default exports
5
6module.exports = { Layout, Header, Container, Footer };
By doing so, you can now import all of these files from the barrel, using JavaScript’s object destructuring.
1import { Layout, Header, Container, Footer } from "../components"; // For ESM
2const { Layout, Header, Container, Footer } = require("../components"); // For CommonJS
Conclusion
Barrels are a great way to make your code more organized and readable, especially when you have lots of modules to import. Combine this with some module aliases and you can greatly improve your developer experience.
It’s worth noting that before you go and implement this pattern, it might be a good idea to take a closer look at the specificities of your project. Most module bundlers are smart enough to deal with barrels, but you might need some additional configuration to avoid causing a circle dependency or increasing your bundle size.
All static files and source code used in this page can be found on GitHub and edited on Codesandbox.
Cover by André Carvalho on Unsplash