How to Structure React Projects
reactjsnews.com
reactjsnews.com
Don't make sub-directories by kind (screens/, controllers/, directives/, views/, styles/, etc), instead encode the kind in the filename (make it a suffix).
Don't end up with a system where you end up often making sub-directories that contain only one file. That's likely an unnecessary level.
The rationale is as follows: your system will never have a fixed number of components, but it quite likely will have a fixed number of "kinds of components." So as your system grows, you will have to group files by feature to deal with complexity. When this inevitably happens, it helps not to have a per-kind directory structure to swim against.
By naming your files with name of concern as a prefix and kind as a suffix, you also get related files together by the virtue of sorting files alphabetically in the same folder (monocline grouping).
The easiest mental model for me is to just map files/folders directly to the route hierarchy. That way you can rapidly build out the overall navigation scheme while building functionality. There are very few subjective decisions besides the route name. New developers can immediately grasp how things are organized and where things belong by interacting with the actual site. If they see a bug, or somebody suggests an improvement on a specific page, they can immediately find the code they'll need to modify.
With features you have to say something like: "Find routes.js, find the route forgot-password within react-router component, see what component it references, now go to top of the file and see the location for that components import. If it's a folder with an index.js file, look in that file and see what component is actually being exported, once you find the underlying component, open that file and try to find the bug."
Anyway, the practical benefit of a feature-first hierarchy is that it makes the changes you need to add a new feature local to a single directory. This means developers don't need to constantly switch between directories in their terminals & file explorer, it lets you implement mechanisms for automated OWNERS-checking or code review, and it means that commit logs will instantly show which feature they touched just from the filenames.
In practice, "feature" is defined by the org chart: it's one concrete improvement that a specific team is working on to benefit the user.
If you're worried about finding the code for a feature on the screen, add a system where if you hover over any component in the UI, it pops up an overlay with a link to the source code. At a previous workplace, an engineer built such a feature in a couple days and it was an absolute lifesaver.
For something like reset password, put it wherever your team will find it. It feels more like auth to me, but if you have most of your auth functionality already built in your settings area, it might not make sense to move it (until it gets unwieldy and "uncomfortable" to keep it there).
Follow the principle of least surprise: if a fellow developer is looking for "reset password," are "settings" and "auth" the only two places where they would look? That's actually good enough. Think about all the times you really had to hunt around to find something that was placed in an unexpected, "weird" place.
Just pick one or the other and be done with it. I'd place it at "auth".
>The easiest mental model for me is to just map files/folders directly to the route hierarchy.
Only files don't correspond 1-1 to the route hierarchy either. The same components can be used in 20 different routes.
Organizing by feature gives you immediate feedback about 'what' the application does, instead of what framework it's written in.
I find this structure much more useful during the application's maintenance lifetime, but it does force you to think more about naming and the division of what a 'feature' is.
See also from Uncle Bob: https://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Arc...
Mind you, that goes against the community “standard,” and we all know how that argument ends up.
Of course you will end up having common folders, the trick is to have more than one and at the appropriate level. Sometimes you need a common folder between a few close-but-not-same components. Sometimes you end up deciding to reuse that common folder elsewhere, so you "promote" it up a few levels.
Other names such as "shared" or even "service" can be used, as long as you put big related pieces in subfolders underneath.
Recognize when things get messy with common folders and refactor then. This is the "trick", so to speak. You have to recognize "our common folders are starting to become a mess" as valid technical debt, because the team will keep having a progressively harder time finding the correct code.
It has:
* react-hot-loader which causes your changed to get automatically loaded into the running webpage
* Webpack, gulp and redux all set up
* A sample api server integrated in the development process to be used with a SPA
* SASS/CSS loading, which also gets hot loaded into your page (once/if my pull request is merged)
* Production builds with minifying and no sourcemaps (once/if my pull request is merged)
I'm not entirely happy with the structuring, but that can always be changed once you're familiar with the technologies. I also just submitted pull requests to address the issues listed in the readme.
https://github.com/erikras/react-redux-universal-hot-example
It's a little heavy, but it includes react-redux bindings, webpack, Babel for ES6 support, mocha for testing, SASS/LESS for styles. There's more info on the GitHub page but it seems to be pretty comprehensive in terms of bundling next-gen front end engineering frameworks.
1. https://github.com/gaearon/redux-devtools/tree/master/exampl...
In my experience, this structure scales very well, especially if you take the advice in the 'thinking in react' tutorial (http://facebook.github.io/react/docs/thinking-in-react.html ) and create a mockup that clearly indicates what part of the UI will be handled with what component.
One of the most confusing things with React and Angular or in fact any other non convention-over-configuration framework is how you go about building your project.
Structure is super important, and this resource looks good.
I would add a demo application on Github that does handle data (something super simple will suffice), just so people can fork the project and take it from there.
I know for me, when I started with Angular, the Yeoman generators were just life savers, I think it would be a great "next stage" for this post.
The gist of it is:
> The file structure maps directly to the route hierarchy, which maps directly to the UI hierarchy.
> It's inverted from the model that we've used in other systems. If we consider all folders being either a "generic" or a "feature" folder, we only have one "feature" folder but many "generic" folders.
[1] https://gist.github.com/ryanflorence/daafb1e3cb8ad740b346
[1] https://github.com/MadeInHaus/react-flux-gulp-starter [2] https://github.com/kriasoft/react-starter-kit
One thing that becomes interesting though, is that all of the advice in the comments here saying "Follow the router!" works brilliantly if you've got a website-style app that you need to build. For us, the router is rather confusing, and all params are optional; it's more of a filter than anything else!
Because of that, we followed the more "convetional" (heh) tree: top level src/ folder, server/, client/, shared/ underneath it. Server and client only hold their respective entry points, and a few modules for the server-side behaviour (middleware and so on).
Under shared/ we have components/ which are separated into folders based on grouped functionality. Like so: https://i.imgur.com/9T0AX52.png
While that's slightly subjective, it worked in our case very well, and at the end of the day solid naming of your components means CtrlP becomes a lot more useful ;)
Could you release your setup somewhere?
https://github.com/shakacode/react_on_rails
https://github.com/netguru/react_webpack_rails
Basically, you introduce webpack as part of your dev/build pipeline, it interacts nicely with the asset pipeline.
I also like to add 'babelify' to my package.json and 'config.browserify_rails.commandline_options = "-t babelify"' to my application.rb to get ES6 goodness.
I'm particularly in awe because I just visited the ReactJS site to find out what all the fuzz is about and it makes the bold claim "just the UI", and "the V in MVC".
The sticking point I found is enabling different lint rule for test and source in a way that doesn't require linting twice and that is automatically understood by my editor (vim + syntastic)
I feel adding vocabulary like this to a system can help with understandability. That's the point I made with a "feature". It's something that could fit between views and components.
Atomic design (http://patternlab.io/) is close to this idea.
Components are "dumb", and just consume props. Views are top level Components, usually rendered by the router, that tie into your fluxy goodness.