kriasoft / react-starter-kit

The web's most popular Jamstack front-end template (boilerplate) for building web applications with React
https://reactstarter.com
MIT License
22.75k stars 4.16k forks source link

What is the best directory layout for a React project? #27

Closed kentcdodds closed 9 years ago

kentcdodds commented 10 years ago

Where to put major components (the ones bound to URLs)

  1. Inside the /src/components folder (e.g. /src/components/issues.jsx) - better for small projects
  2. Inside the /src/pages folder (e.g. /src/pages/issues.jsx, /src/pages/questions.jsx) - might be better for small projects
  3. A separate folder for each major component (e.g. /src/issues/index.jsx, /src/issues/new/index.jsx) - might be better for medium-size projects
  4. A separate folder for each section (area) of the site (e.g. /src/account/login.jsx, /src/account/profile.jsx, /src/account/settings.jsx)

    Where to put unit test files

  5. test folder in project's root (e.g. /test/components/navbar-test.js)
  6. test folder in each source folder (e.g. /src/components/test/navbar-test.js)
  7. Unit test within the same folder with a component (e.g. /src/components/navbar-test.js)
  8. Should it be test or __test__ folder (see React source code)

@koistya:

Kent,

What do you think about this directory layout (assuming it's a github.com application):

/src/issues/index.js - the main component bound to the /{repo}/issues URL /src/issues/index-test.js - unit tests for it /src/issues/index.less - CSS styles for the page /src/issues/new.js - the component bound to the /{repo}/issues/new URL /src/issues/new-test.js - unit tests for it /src/issues/new.less - CSS styles for the page

Though, this kind of layout might be too advanced for a starter kit project..


@kentcdodds:

I am in the process of rewriting my website from angular to react. You can look at my gulpfile for an example ofa jest configuration that would support that file structure: https://github.com/kentcdodds/kentcdodds.github.io/tree/dev

You can also see how my stylus is setup as well.

As far as your recommended file structure, I think I like it. The one issue I would have is what if you decided to have a state below /new? In that case, you'd need to have a folder for that state, so I would change it like so:

/src/issues/index.js - the main component bound to the /{repo}/issues URL /src/issues/index-test.js - unit tests for it /src/issues/index.less - CSS styles for the page /src/issues/new/index.js - the component bound to the /{repo}/issues/new URL /src/issues/new/index-test.js - unit tests for it /src/issues/new/index.less - CSS styles for the page

For testing purposes, you may also want a -mock.js file for some components where that makes sense.

Also, as far as components go, I would say that you want the component files to be as close to where they are used as possible.

Do, if a component is specific to /new, then it would be in that directory, however, if it's shared between /new and /edit, I would put it in the nearest common parent directory (like /issues). Then if there's a component that's shared with everything, then it would go in /src

You may want to make a components folder to hold those kinds of components (so there'd be one in /new, /issues, and /src in that precious example).

Let me know what you think. I've never built a big application in react, so this is loosely based on my experience with angular. I think it's sound though.


@koistya:

Yeah, having tests along-side to code under test sounds very appealing to me as well. Having a folder for each page of the site on the other hand may lead to too many folders, nesting.. I usually prefer to avoid too deeply nested folders.


@kentcdodds:

I agree with avoiding nesting folders too deeply. I don't see a problem with new.js for /new. If you needed to add a sub-state for that, it wouldn't be too difficult to move things around for it. But I think that the file structure should reflect the routes in some reasonable way. This makes the repository easier to reason about.


@koistya:

Yeah, totally agree. One thing which I'm trying to solve is to how to place these URL-bound folders to other stuff like /stores, /actions, /constants and other JavaScript folders... should they have the same parent folder.. maybe not


@kentcdodds:

Good question... I like something like this:

src

  • bower_components
  • non_bower_components
  • app (not sold on this name, in angular I'd name it "components" but in react that has a different meaning)
    • stores
    • actions
    • constants
    • components
    • issues
      • index.js
      • new.js
    • repos
      • index.js

etc.

Though, I'm starting to wonder if maybe the stores/actions/constants are specific to a feature (like issues) then maybe it should exist in that folder. I like to keep things grouped together to the point that you could almost think of that folder as an entry point to a npm module. So, if that folder has any dependencies outside of itself, it's because some other folder depends on it as well. Does that make sense? I like to keep things as close to where they're used as possible.


@koistya:

inside /src folder you have front-end code inside the /app folder and server-side code in /src/server or something like that? From what I see (yeoman templates) they either use /src or /app folder for the web application code.. the difference is if your app can be launched from the same folder, it's usually called /app and if you app can be launched only from the /build folder then source code is usually placed into /src.


@kentcdodds:

Sorry, no, everything from the /src folder down is client-side code, as yours is currently.


@koistya:

Then why to use /app inside /src ? maybe /app in the root level, or having your code in /src would do a better job (less nesting)? I personally prefer putting bower_components, node_modules outside the source folder... at this moment i don't even use bower, because everything I need is on NPM, and browserify or webpack bundles the source code along with 3rd party dependencies into custom bundles (./build/app.js), the bower_components folder is never deployed to a server.

kentcdodds commented 10 years ago

That's a good point... I don't use bower_components in react either. That must be an artifact of angular in my brain... Perhaps you could take that out and put everything I have there in /app up a level. And remove non_bower_components and call it non_node_modules.

kentcdodds commented 10 years ago

non_node_modules is weird though... Maybe you could just be sane and call it vendor...

koistya commented 10 years ago

non_node_modules.. I name it vendor (a folder for 3rd party libraries which are not in either npm nor in bower).

kentcdodds commented 10 years ago

That's reasonable.