Originally posted here https://medium.com/octopus-labs-london/how-to-structure-files-in-large-react-projects-48ee3dc424ed
Okay I admit, I've got your attention with a somewhat catchy title but hear me out.
When you tend to have large React, Svelte, Vue, any frontend framework (or library) project, it's easy to put all the components in a components folder, containers in the containers folder and so on. Well I have a different approach for really large projects. Something that looks a bit like this
public/
package.json
index.ts
src/
│
├── components/
│ ├── Button/
│ │ ├── Button.tsx
│ │ ├── Button.tests.tsx
│ │ └── Button.css
│ ├── Dropdown/
│ ├── Toaster/
│ ├── Header/
│ └── Footer/
│
├── layouts/
│ └── StoreLayout/
│ ├── components/
│ │ ├── SearchDropdown/
│ └── StoreLayout.tsx
│
└── pages/
├── StoreProductPage/
│ ├── components/
│ │ ├── Carousel/
│ │ └── ProductCard/
│ └── StoreProductPage.tsx
│
└── StoreCheckoutPage/
├── components/
│ └── ProductCheckoutCard/
└── StoreCheckoutPage.tsx
This way it's easy to remove pages without other parts of the site. All the general components go in the components folder. But Page specific components go in a sub-folder.
Not quite convinced?
Check out my video explanation on YouTube.
Let's talk
It would be good to hear your thoughts on this approach, if you like or dislike it, and if you have any ideas for improvements. You can find me on the socials, or you can just write a comment below and I promise I'll respond 🙏
Top comments (10)
Every component is meant to be on a page or more, or even inside another component or more (think of button component as example).
Then, if you put some
components
afterpages
, what will happen is that anytime you need to reuse one of those components in a different place you'll need to refactor for no other reason than an inefficient project structure.Components are components, layouts are layouts and pages are pages. Mixing them on opinionated or situational shape is usually bad (unnecessary refactors during project further developments). There's why I'll keep adding every single component below
components
.I think this depends on how you structure your project. If you structure it based on pages which is what I have done then yes, there will be components that are shared between pages and this could go in a
components
directory. But there will be many components that are only used on one page. In this scenario I would suggest on having a components folder in that page folder so that if you ever had to delete that page, all the components specific to that page go as well.Running a tool (JSLint or any other) to spot "unused" components (a.k.a. functions) is more reliable in such situations, and setting a components folder in each "view/page" still has the issue of having to refactor whenever you need a component in a different view.
Re-imagine things is always good, but the requirement to be successful while doing so is to understand why things are the way they are. If everyone is having a single "components" folder is not by personal preference but for a project maintainability benefit, and because the nature of the components is precisely to be reusable... using a component just once is just a temporal coincidence, and is better to be ready for when that coincidence doesn't happen to exist anymore.
If I were to use a title as bold as you have, I would have accompanied it by introducing a very radical opinion in regards to a new file structure; I don't consider this to be radical.
I'm not a fan of this style personally, I prefer a flatter hierarchy and having a nested components section within layouts and pages subfolders sounds like more maintenance than benefit. What happens when I realize
StoreProductPage/components/ProductCard
is needed for theStoreCheckoutPage
page?the tl;dr here is that it doesn't matter how you lay out your projects, so long as you/your team understand it.
Yeah I agree with your last point. This file structure is something I've found very useful particularly for large projects. Maybe for much smaller projects the flat hierarchy works, but imo it falls apart when you're chopping and changing a lot for med to larger projects.
We’ll have to agree to disagree as far as limitations for a flatter hierarchy, I build enterprise SaaS and there aren’t many projects that have a larger scope than I do - unless of course you’re building the UI for GCP or AWS
Fairplay. I think whatever works for you and your team is good. I've worked on an app with a flat structure where we had to delete a huge chunk of it. We mostly left components folder as is because we weren't sure where the components were being used so the codebase has a bunch of components that potentially don't need to exists.
We could have done a project wide search and looked through the imports to see what was being used where but in hindsight, it would have been easier to delete pages if we had more of a complex file structure like the one I proposed above.
If you look at frameworks like Nextjs and Svelte, they are moving to folder based routing instead of file based routing so that the a folder for a specific page can contain the pages, styles, tests and even components that are only used for that page.
I have a similar approach for spring boot or quarkus projects (Java).
When I learnt it at school and through tutorials, I always saw the type driven approach, packages like database, controllers, views. But after experimenting a bit, I found component/functionality driven approach to be much more suitable: the package (folder) should group everything related to a given functionality. It is clearer, cleaner, and easier to understand without looking all over the place.
The only thing here is the need for meaningful and consistent suffixes a cross packages/folders: FooDb, FooDao, FooController / BarDb, etc.
My point is, this may apply to every language, and I completely agree with you!
Too much nested and duplicated responsibility to my like.
I found very intuitive the atomic Design approach to organize general components.
And a flat structure easier explore and maintain, but it's a subjective topic I guess.
Yeah it's a good point, everyone is different. In my opinion, the approach I've shared above works best for medium to large project that have upwards of 50 components. If say 10 of those components only belong to the settings page and for some reason you have to delete the settings page, say it's moving into its own repo. It's much easier to do that with the file structure that I've proposed than using a flat structure.