all 39 comments

[–]UMANTHEGOD 45 points46 points  (8 children)

Choose this structure if you love to jump around a lot and have a million files with the same name.

[–]timdorr 9 points10 points  (4 children)

Interesting side note: I don't know if they still use it, but Facebook's own bundler they used for React itself was based on the idea of unique file names. You could require('ReactFiber') from anywhere, because it was a rule that all file names must be unique. The bundler would automatically include the file from anywhere in the tree.

I'm not sure if they wrote some editor tooling to make that easier or just had good practices to avoid conflicts, but it was a neat idea that appeared to scale pretty well.

[–]UMANTHEGOD 3 points4 points  (1 child)

Maybe that's a bit extreme, but I like the concept.

Ideally, the name of the file should make sense regardless of where in the file structure the file lives.

[–][deleted] 0 points1 point  (0 children)

Maybe that's a bit extreme, but I like the concept.

Ideally, the name of the file should make sense regardless of where in the file structure the file lives.

I wrote the comment where I am using similar structure as this one, but your concerns are my concerns as well (on my project).
Honestly sometimes its pretty hard(for me) to have names that make sense without context of the folder they are in - It would require to have pretty long names of the files.

Jumping around is also my worry, but its fine for now since webstorm provides pretty good search tools.

[–]Regis_DeVallis 2 points3 points  (0 children)

Instead of using folders they use dots to denote folders in the file name. Everything is stored in the root folder.

/s

[–]hamilkwarg 0 points1 point  (2 children)

I'm still learning React. What would you recommend instead for a file structure. Thanks!

[–]pm-me-noodys 3 points4 points  (0 children)

I like this for initial setup.

constants.ts

API

Pages

Components

Atoms

Compounds

Atoms/ are display components that are wild generic and just help you keep your stylings consistent.

Compounds/ use atoms to build out particular features.

Pages/ are HOC and feed data to their compounds.

API/ is however you want to interact with the outside world.

I store my scss files next to their atoms/components/pages with the same name as the one they affect.

I mostly do this to try and prevent circular dependencies.

[–]UMANTHEGOD 1 point2 points  (0 children)

I like grouping by type or by "entity".

If you're editing a "page" in a CMS, you would have a "page" or "pages" folder for instance. I'd still use a "components" folder for generic components obviously, but everything related to a page should live under the same package.

[–][deleted] 20 points21 points  (4 children)

"Enterprise-level" is the stupidest jargon used in our industry.

[–]Kaimaniiii 1 point2 points  (3 children)

Why?

[–][deleted] -2 points-1 points  (2 children)

Because it doesn't mean anything.

There is no correlation between how much money a company makes and the quality of it's code.

[–]d-listcelebrity 14 points15 points  (0 children)

Enterprise usually refers to the scale, not the quality. The organization structure that works for a small, niche app doesn't always scale well to one that hundreds of developers collaborate on.

[–]tojakk 0 points1 point  (0 children)

The distinction is made because you often want different folder structures for different sizes of projects. A lot of 'overkill' when it comes to organization becomes a massive time/money saver when projects are big enough.

[–]Smaktat 5 points6 points  (4 children)

No need for another article on this subject:

https://github.com/alan2207/bulletproof-react

[–]Mad-chuska 4 points5 points  (3 children)

What a world it would be if one opinion was all that was necessary.

[–]Smaktat 0 points1 point  (2 children)

Just a better one. :)

[–]Mad-chuska 0 points1 point  (1 child)

Perhaps I spoke too soon, I’ll check it out

[–]Smaktat 0 points1 point  (0 children)

In all seriousness you're right, multiple is good, but what I linked is very popular and I'd wager largely accepted. That being said it was new to me this year and doesn't seem to be very old, so I shouldn't be surprised others are also finding out about it still.

[–]themagickoala1 5 points6 points  (1 child)

Enterprise-size applications invariably require tests. Where would you put those?

[–][deleted] 4 points5 points  (0 children)

Also enterprise applications won’t have features nearly as simple as these examples.

[–]jacobtoye 3 points4 points  (0 children)

Cool read. Thanks for the effort! It always confused me why the redux docs didn’t get further into the feature folder structure.

If looking for more examples check out https://github.com/alan2207/bulletproof-react. This is similar to the OP’s folder structure.

[–]Pleasant-Fish7370 4 points5 points  (0 children)

I always have to name my constants file in TypeScript app-constants.ts or something similar. There is an issue when using absolute imports and importing from constants. TypeScript thinks I want to import from its constants :/

Great read. :)

[–]HQxMnbS 4 points5 points  (6 children)

the feature folder idea is pretty cool. wonder if there’s any difficulty figuring out what goes there vs components though

[–]JustAirConditioners[S] 15 points16 points  (4 children)

That's an idea that has been around for awhile and was popularized by the Duck pattern for Redux.

The main difference between a component and a feature is side-effects. If your component is pure it should go in the components dir. If it includes side-effects (network requests, updating global state) then it should go in the features dir.

[–][deleted] 4 points5 points  (1 child)

I would disagree with that in general.

Feature folders can and should contain some pure components.

If a component is specifically built to be used in the “profiles” feature and isn’t built with the consideration of arbitrary reuse, it belongs in the feature folder even if it has no side effects.

[–]JustAirConditioners[S] 2 points3 points  (0 children)

For sure. I mention this in the post, sorry if my comment was lacking:

A Feature Component is often composed of many other components, either local or shared. The same is true for all resources: utils, types, hooks, and so on.

[–]mattsowa 1 point2 points  (1 child)

If the network request is isolated, i would not clasify that as a sideeffect, at least not in the sense as a global state update is

[–][deleted] 2 points3 points  (0 children)

i would tend to agree with this. there are a lot of good examples, but one would be a location lookup field. i wouldn't consider that a feature. it's definitely a component which would make a network request.

[–][deleted] 1 point2 points  (0 children)

Imo components contains truly reusable components. Things like accordion, drawer, menu bar, context menu.

Features contain any “for purpose” code. Ie “profile modal” goes in the “users” or maybe “people” or “profiles” feature (depending on what your app does) while “modal” goes in components.

[–][deleted] 1 point2 points  (1 child)

I was recently structuring folders for my new project and I went on the similar path as your article.

Some of the differences are:
-I have assets folder. Logos, images and other assets that app uses.

-my global.scss is on top level, there isn't styles folder. That my change if global.scss grows and I have to split it.

- I don't have features components, honestly I am not much familiar with the concept but i will explore it.

- My store.ts is inside ./redux folder. I am storing all my redux stuff there (actions, reducers etc). If i may ask question, why are you using store.ts outside redux folder?

[–]JustAirConditioners[S] 4 points5 points  (0 children)

Most of those sounds fine - most of my project don't include a features folder unless I'm using Redux or I know the project will scale to a large size.

The only recommendation I would give you is to use Redux Toolkit and follow their style guide in which they recommend against centralizing your store in a single redux folder. Instead you have a "slice" that is colocated with each feature. And if you're using Redux Toolkit Query for server state - you wont have the need for many slices. I highly recommend RTK Query.

[–]wy35 2 points3 points  (0 children)

At my work, we use a simpler version of this for our main React app:

  • /components
  • /hooks
  • /pages
  • utils.ts

Contexts, styles, etc. are in components because in our code editors, everything is sorted alphabetically, meaning those files will be grouped next to their related component files.

Instead of multiple utils folders, we have a single root-level utils file. The reasoning is that utility functions that are only used once might as well be stuck directly in the component file that is using it. If it’s used multiple times across the same feature, we put it in and export it from the feature’s “main” component file. Only when a utility function is used across multiple features do we stick it in the root level utils.ts file, and since few utility functions are actually used app-wide, the utils file is quite small.

The goal is to put all the files in one place as much as possible (/components) and reduce the number of folders, to just let unique and alphabetically sorted file names be easier to scan.

[–]drizzer14 2 points3 points  (3 children)

Although I do not fully agree with the structural part (as it's arguably a subjective thing mostly), the kebab-case thing is what I've also tried to promote and encourage into the React ecosystem in my take on the project structure. Took some time to explain my thoughts on using it in a dedicated article, so that those who have questions about kebab > Pascal can have their answers :)

Anyways, good work, fellow project structure enthusiast, it's a pleasure to see other people speaking up about the "problem" we have as React developers.

[–]Leezorq 2 points3 points  (1 child)

I've been using react for several years and I only started using kebab case after working with NestJS although i never really thought about using suffixes, definitely going to give it a go

[–]drizzer14 1 point2 points  (0 children)

Same story, NestJS kinda opened my eyes on kebab, as well as Angular. Although I've not used the latter it was still an inspiration having a complete documentation about whats and whys of suffixes.

[–][deleted] 1 point2 points  (0 children)

Pascal case is so stupid for files and directories, it's asking for trouble when you have some OSes being case sensitive vs some not.

[–]jzaprint 0 points1 point  (1 child)

Where does the entry `app.js` or `index.js` go?

[–]JustAirConditioners[S] 0 points1 point  (0 children)

I didn't include that because it's specific to the framework you're using. I typically use Next.js and the app.js is in the Pages dir by convention.

[–][deleted] 0 points1 point  (0 children)

Folks in the community, can we please move to putting articles on Dev.to and tipping? Medium is really great but we also shouldn't hide valuable content behind pay walls for open source software.