DEV Community

Cover image for Organize React Components Better with Barrel Exports
Joe Ziemba
Joe Ziemba

Posted on • Originally published at blog.justmyrealname.dev

Organize React Components Better with Barrel Exports

We all know that React imports can get a little... verbose.

import * as React from "react"
import compose from "recompose/compose"
import type Dispatch from "redux"
import connect from "react-redux"
import querystring from "query-string"
import generateMetaInfo from "shared/generate-meta-info"
import Head from "../../components/head"
import SegmentedControl from "../../components/Layout/segmentedControl"
import ChannelProfileCard from "../../components/Layout/entities"
import CommunityAvatar from "../../components/Layout/avatar"
import ErrorBoundary from "../../components/error"
import MembersList from "./components/MembersList"
import PostFeed from "./components/PostsFeed"
import SidebarSection from "../../components/Layout/SidebarSection"
import CommunitySidebar from "../../components/communitySidebar"
import FeedsContainer from "./style"
import InfoContainer from "../community/style"
import FullScreenRedirectView from "../../views/viewHelpers/fullScreenRedirect"
// and this isn't even that long...
Enter fullscreen mode Exit fullscreen mode

The node module imports are unavoidable, but we can clean up our local imports
with a pattern called barrel exporting.

The Barrel Export

import {
  ChannelProfileCard,
  CommunityAvatar,
  CommunitySidebar,
  ErrorBoundary,
  FeedsContainer,
  FullScreenRedirectView,
  Head,
  InfoContainer,
  MembersList,
  PostFeed,
  SegmentedControl,
  SidebarSection,
} from "../../components"
Enter fullscreen mode Exit fullscreen mode

A lot easier on the eyes, eh?

Barrel is about more than the aesthetic though. We get better Intellisense and auto-importing for components in editors like VSCode thanks to the named exports, along with more flexibility in organizing our filesystem. We can nest folders as deep as it makes sense without worrying about ballooning import statements.

How to set up Barrel Exports

A traditional export/import setup for React looks like this:

// src/components/SidebarSection/index.js

const SidebarSection = (props) => {
  /* implementation */
}

export default SidebarSection
Enter fullscreen mode Exit fullscreen mode
// src/views/Homepage/index.js

import Error from "../../components/error"
import Row from "../../components/Layout/blocks/Row"
import SidebarSection from "../../components/Layout/SidebarSection"
Enter fullscreen mode Exit fullscreen mode

To enable the Barrel pattern, all we need to do 2 things:

  1. Change from a default to named exports.
  2. Add an index.js in whatever directory you want to be "the Barrel." From this file, we'll re-export all our components in that branch of the filesystem.
// src/components/Layout/SidebarSection/index.js

export const SidebarSection = (props) => {
  /* implementation */
}
Enter fullscreen mode Exit fullscreen mode
// src/components/index.js

// This is the Barrel!

export { Error } from "./Error"
export { Row } from "./Layout/blocks/Row"
export { SidebarSection } from "./Layout/SidebarSection"
Enter fullscreen mode Exit fullscreen mode
// src/views/Homepage/index.js

import { Error, Row, SidebarSection } from "../../components"
Enter fullscreen mode Exit fullscreen mode

And that's it!

What's Next

In future posts we'll look at even more improvements we can make to our React code with patterns like dot notation and removing the need to relative imports. Follow me on Twitter @justmyrealname to hear when new articles drop!

Discussion (8)

Collapse
pcjmfranken profile image
Peter Franken

Barrelfile exports come with many gotcha's if you want tree-shaking to work. Something to keep in mind and test on your own setup.

Related open issue at Nextjs: github.com/vercel/next.js/issues/1...

Collapse
justmyrealname profile image
Joe Ziemba Author

Thanks Peter, good to know for people using Next.js! I haven't run into that problem using standard CRA luckily.

Bit of a tangent, but I it's worth noting why no tree shaking is hurting them there:

There's about 100 components defined, and only a couple are used

Unused components - especially that many - really should be deleted. Having build tools help with our bundle size is great, but shouldn't replace our own clean code practices. We don't want our codebases to start looking like an episode of Hoarders! 😄

Collapse
ashoutinthevoid profile image
Full Name

The full quote is important here

There's about 100 components defined, and only a couple are used in _app.tsx.

Only a few used in that specific file, _app.tsx. That's not the same thing as having only a few used in the entire application. That file initializes every single page; if every component was used in every single page, there would be nothing to shake.
The absence of tree shaking is not a hoarding problem, it's a legitimate bug in this next.js case.

Thread Thread
maciekgrzybek profile image
Maciek Grzybek • Edited on

First of all, great stuff with the article :) I've been using this pattern for a while now, but never knew that it's called like that :)
Is the tree shaking problem only related to next js?

Thread Thread
pcjmfranken profile image
Peter Franken

Not limited to Next. Whether your codebase is affected depends on its complexity and your bundler configuration. Running some tests is the only way to to be sure.

Figuring out what code can be safely dropped ("tree-shaken") is quite complex. Your bundler (e.g. webpack) has to look at each piece of code and figure out if it's used anywhere else in any way (deep-scope analysis).

The more ambiguous your code or deeper your import trees, the more time it would take to get this right (exponential complexity AKA best leave it for the CompSci's 😉). We want fast builds though, so at some point the bundler is just going to tap out and leave the code that it isn't sure about in.

Here's an amazing and really in-depth article for those wanting to learn more: dev.to/livechat/tree-shaking-for-j...

Collapse
alaindet profile image
Alain D'Ettorre

Finally, someone talking about our Lord and Savior the barrel file

Collapse
justmyrealname profile image
Joe Ziemba Author

Amen 🙏 Such an underrated pattern!

Collapse
alaindet profile image
Alain D'Ettorre

I literally use it everywhere, in any language (including SCSS!) and I'm starting to get grumpy about languages not having it.

Other than imports, the cool thing about it is being able to truly refactor features without breaking anything, since features are often contained in their own directory. Also, it's basically mandatory if you want to build any NPM package.