React Project Architecture using Barrels

Written by chrishouse | Published 2018/08/07
Tech Story Tags: javascript | react | angular | tutorial | typescript

TLDRvia the TL;DR App

When scaffolding out a large application, you will have to refactor your import statements quite a lot. Barrels will make it easier.

A barrel is a way to rollup exports from several modules into a single convenient module. The barrel itself is a module file that re-exports selected exports of other modules. Source:https://basarat.gitbooks.io/typescript/docs/tips/barrel.html

Angular 2+ uses barrels quite extensively, and I was trying to figure out how to use this in react. I started on my journey to create a react app via create-react-app.

Why use barrels?

In enterprise development with multiple teams, if you ever want to change your project structure around, it could be a nightmare once every branch gets merged together. Think multiple teams all on different sprints all using some shared/core functionality. What I have seen happen is one team refactors some shared/core code, and breaks the imports everywhere.

In my example, I have a NavBar component that lives under the path `./components/layout/Navbar’; and at the bottom of the React Component, you will see:

export default NavBar;

In my App.js where I will be injecting this NavBar component, I have to first import it along with my other layout components:

import NavBar from './components/layout/NavBar.js';import SidebarMenu from './components/layout/SidebarMenu.js';import Content from './components/layout/Content.js';import Footer from './components/layout/Footer.js';

Barreling gives me a way to reduce these four lines of code into:

import { SidebarMenu, Footer, Content, NavBar } from './components';

You can also take it a step further and alias everything that is exported form the component folder, and import all of it.

import * as comp from './components';

Inside my App.js component, I can refer to any of the components by prefixing it with comp. So to refer to my NavBar, I just use <comp.NavBar />

The beauty of this is if I change the location of NavBar component from `./components/layout/Navbar’; to `./CoreModule/Shared/Layout/Navbar’;

I wont have to refactor my App.js component’s imports.

How does it work?

The way I chose to structure my application is that each component gets its own folder. The contents are the component js file, the components css file, and the index.js file that does the barreling for us.

The contents of index.js inside this component folder:export {default as NavBar} from "./NavBar";

The important word I missed when beginning my barreling journey was default. In your bottom most component, you must export your default class.

Parent folders only need to export there 1st level children exports.

Notice you are not exporting default class anymore. When you say default as NavBar You are renaming the default export.

this is the next level above layout

top level module

For the commit that implements this change you can see: https://github.com/crh225/react-firebase/commit/f3cda6732b3aafe0b2283f19b7ea89e82cc85ed6

Repo: https://github.com/crh225/react-firebase

Further reading about barrels in Typescript: https://basarat.gitbooks.io/typescript/docs/tips/barrel.html


Published by HackerNoon on 2018/08/07