React Architecture: File Structure for Scalable projects

React Architecture: File Structure for Scalable projects

Introduction

Organizing a React app is one of those things that don't have an absolute right or wrong way of doing it, but depending on the structure, you could make your life slightly or way less painful. Some of us, never think about how we want our React project structured at the beginning of the project because it is non-opinionated. It works no matter how we decide to structure it, provided the imports check out. It’s as the project grows that you might start to regret your file structure and be forced to reorganize the whole thing which, to be honest, is not a lot of fun to do.

In this article I'm going to show you what I consider to be a "just-right" and scalable file structure for intermediate and large-scale production React Applications which I have come to develop from research and some experience working on several large-scale React apps.

Architecture by File-Type

In a typical React application i.e after running npx create-react-app, the file structure is organized based on the component paradigm, where each component has its folder and files and each folder, has its files and sometimes folders too and so on. Here's a typical structure:

my-react-app/
├── node_modules/
├── public/
│   ├── index.html
│   └── favicon.ico
│  
├── src/
│   ├── components/
│   │   ├── Navbar.js
│   │   ├── Footer.js
│   │   └── ...
│   ├── styles/
│   │   ├── Navbar.css
│   │   ├── Footer.css
│   │   ├── Home.css
│   │   ├── Register.css
│   │   └── ...
│   ├── pages/
│   │   ├── Home/
│   │   │   └── Home.js
│   │   ├── Register/
│   │   │   └──  Register.js
│   │   └── ...
│   ├── App.js
│   ├── index.js
│   └── index.css
│  
├── package.json
└── README.md

Well, technically, Create-react-app doesn't come with the pages, styles or components folder. It's common sense and an instinct to want to have that folder. This architecture is focused on file type as opposed to a feature. Notice how all CSS files are in the styles folder, and all modularized reusable JS code are together in the component folder. This structure works, it's simple and great for small-size projects but this could develop into a monolithic application as the project gets bigger, making it messy and more difficult to work with. Imagine having about a hundred different CSS files or a few hundred more reusable components. See? Not great for large-scale projects.

Architecture by Feature

This is what I like to call a "just-right" and scalable file structure. Structuring a React app by feature means organizing the codebase of the app around specific features or user stories. This approach groups together all files related to a particular feature together in one place, making it easier to understand, test and modify the feature in the future without affecting other parts of the app. This will prove very helpful when the project grows.

If you're structuring your React app this way, it means that code related to a feature (sometimes referred to as a module) in the app is organized into a directory named after that feature. For example, if the app has a register feature, all the code related to the register feature, including the React components, CSS styles, helper functions, custom hooks, API requests, and tests, will be located in the directory named 'register'.

It doesn't end there, within a feature directory, the code can be further organized into subdirectories based on the file type. For example, the 'register' feature might contain subfolders for components, assets, styles, helpers, hooks, API, and tests. Please don't just create all these folders within the feature directory, do so only when the feature needs it. i.e you could have a feature with a test, components and styles folder without the hooks or API folder and another feature with the API, helper and no styles or component folder. You just have to create these subdirectories based on the feature requirements.

/src
├── common/
│   ├── components/
│   ├── helpers/
│   ├── styles/
│   ├── tests/
│   └── utils/
│
├── dashboard/
│   ├── components/
│   │   ├── Dashboard.jsx
│   │   ├── DashboardChart.jsx
│   │   ├── DashboardTable.jsx
│   │   └── DashboardWidgets.jsx
│   ├── styles/
│   ├── helpers/
│   ├── tests/
│   └── api.js
│
├── authentication/
│   ├── components/
│   │   ├── /LoginForm.jsx
│   │   ├── /SignupForm.jsx
│   │   ├── /ResetPassword.jsx
│   │   └── /VerificationEmail.jsx
│   ├── pages/
│   │   ├── Login/
│   │   └── Signup.jsx/
│   ├── styles/
│   ├── helper/
│   ├── tests/
│   └── api.js
│
├── settings/
│   ├── components/
│   │   ├── UserProfile.jsx
│   │   ├── UserSettings.jsx
│   │   ├── ChangePassword.jsx
│   │   └── NotificationSettings.jsx
│   ├── pages/
│   ├── styles/
│   ├── helpers/
│   └── api.js
│
├── landing-page/
│   ├── components/
│   │   ├── HeroSection.jsx
│   │   ├── FeaturesSection.jsx
│   │   ├── PricingSection.jsx
│   │   └── ContactSection.jsx
│   ├── styles/
│   ├── helpers/
│   └── api.js
│
├── routes/
│   ├── .../
│   └── index.js
│
├── app.js
├── index.js
└── ...

In this example, the app is organized into four feature directories: dashboard, authentication, settings, and landing page. Each feature directory contains subdirectories for components, styles, pages, helpers, tests, and whatever else the feature needs.

It is also important to notice that the common directory contains code that is used across multiple features, such as common components, styles, tests, and functions.

Now imagine the app grows to have a few hundred CSS files among these 4 features. All these css files won't be in one place, they'd be split between the features based on which feature uses it and CSS files shared among several features would be in the common directory. You can start to see how easy it would be to find the styles you'd need depending on what feature you're currently working on.

Overall, structuring a React app by feature can help keep the codebase organized and modular, making it easier to maintain and scale as the application grows.

Bonus

As a "thank you" for reading this lengthy article, I have a bonus for you.

We have taken a look at two architectures and even though the latter is a more efficient approach and has been given the developer's choice award on several occasions (This is a joke by the way), there are certainly other ways to structure your code that can help make your React project more organized, maintainable and scalable.

I developed a structure template that I tend to use more often with intermediate-size projects. It is a modification of the first architecture I shared with us in this article. It's like an architecture by file type but on architecture by feature steroids.

│
├── src/
│   ├── assets/
│   ├── data/
│   ├── hooks/
│   ├── styles/
│   │   └── components/
│   │       ├── form/
│   │       └── interface/
│   │    
│   ├── tests/
│   │   └── components/
│   │       ├── form/
│   │       └── interface/
│   │    
│   ├── components/
│   │   ├── form/
│   │   │   ├── Search.js
│   │   │   ├── Select.js
│   │   │   └──  Select.js
│   │   ├── interface/
│   │   │   └──  LoadingPage.js
│   │   └── ...
│   │   
│   ├── pages/
│   │   ├── Home/
│   │   │   ├── components/
│   │   │   │   ├── Header.js/
│   │   │   │   └── Footer.js/
│   │   │   ├── tests/
│   │   │   ├── styles/
│   │   │   └── index.js
│   │   │  
│   │   ├── Login/
│   │   │   ├── components/
│   │   │   │   ├── LoginForm.js/
│   │   │   │   └── ForgotPasswordForm.js/
│   │   │   ├── tests/
│   │   │   ├── styles/
│   │   │   └── index.js
│   │   └── ...
│   ├── App.js
│   ├── index.js
│   └── index.css
│
├── package.json
└── README.md

In this example, there are a couple of things that are worth noticing.

  • Notice how the "components" folder on the root directory now has subdirectories with descriptive names representing the type of components it contains.

  • The "pages" subdirectories are treated as a feature(module) and it houses all files related to that page. Including styles, tests, helper functions, React components and more.

  • Now that all pages have it's own files grouped, we can now use the components folder in the root directory for common components: components used across more than one page. Same for other folders in the root directory as well like the hooks, styles, tests, helper and API folders

Just like I said in the opening of this article there's no right or wrong way. React file stucture is totally flexible and you have full power to decide how you want to do it. I only advice that you take an approach that creates lesser pain.