Skip to content

Instantly share code, notes, and snippets.

@lancejpollard
Created November 28, 2011 01:50
Show Gist options
  • Save lancejpollard/1398757 to your computer and use it in GitHub Desktop.
Save lancejpollard/1398757 to your computer and use it in GitHub Desktop.
What is your folder-structure preference for a large-scale Node.js project?

What is your folder-structure preference for a large-scale Node.js project?

0: Starting from Rails

This is the reference point. All the other options are based off this.

|-- app
|   |-- controllers
|   |   |-- admin
|   |   |   |-- postsController.js
|   |   |   `-- usersController.js
|   |   |-- postsController.js
|   |   |-- sessionsController.js
|   |   `-- usersController.js
|   |-- models
|   |   |-- post.js
|   |   `-- user.js
|   |-- views
|   |   |-- admin
|   |   |   `-- posts
|   |   |       |-- edit.jade
|   |   |       |-- index.jade
|   |   |       |-- new.jade
|   |   |-- layouts
|   |   |   `-- application.jade
|   |   `-- posts
|   |       |-- index.jade
|   |       `-- show.jade
|   `-- helpers
|       |-- admin
|       |   |-- postsHelper.js
|       |   `-- tagsHelper.js
|       `-- postsHelper.js
`-- config
|    |-- application.js
|    |-- locale
|        `-- en.js
|    |-- routes.js
`-- lib
`-- spec
|    |-- helper.js
|    |-- models
|    |   |-- postSpec.js
|    |   |-- userSpec.js
|    `-- acceptance
|        |-- loginSpec.js
|        |-- signupSpec.js
|        `-- postsSpec.js
`-- vendor
|    |-- javascripts
|    |   |-- jquery.js
|    |   |-- underscore.js
|    `-- stylesheets
|        `-- prettyPhoto.css

1: Rails-like, with nested /app folders for client, mobile, etc.

|-- app
|   |-- controllers
|   |-- models
|   |-- views
|   `-- browser
|       |-- controllers
|       |-- models
|       |-- views
|   `-- mobile
|       |-- controllers
|       |-- models
|       |-- views
`-- config
`-- lib
`-- spec
`-- vendor

Pros:

  • lends itself great to progressive enhancement so-to-speak. You start with just /app, and if your app starts growing, you add sub directories.
  • doesn't pollute the top-level directories, which have a pretty uniform convention across apps. However, people do add /themes to the top level, which is just about the same as adding /client to the top-level.

Cons:

  • Now you have /app/models and /app/browser, etc., which isn't a totally clear naming convention -- /app/models is for a subset of code for the server, while /app/browser is a totally different app. It's different than a namespace like /app/models/admin though, which makes sense.

My vote: no

2: A /app/client folder, similar to Rails' /app/assets

|-- app
|   |-- controllers
|   |-- models
|   |-- views
|   `-- client
|       `-- browser
|           |-- controllers
|           |-- models
|           |-- views
|       `-- mobile
|           |-- controllers
|           |-- models
|           |-- views
`-- config
`-- lib
`-- spec
`-- vendor

Pros:

  • The main reason you need these extra folders is for the different clients for the app. So putting them in /app/client conceptually makes a lot of sense. It's easy to reason about.
  • Similar to Rails, which has /app/assets/javascripts instead of /app/client. You don't want to start naming the folder /app/assets because, conceptually, everything is JavaScript, and calling one chunk of JavaScript "assets" and the rest "app" is conceptually jarring.

Cons:

  • You have deeply nested folders for core code, which can be annoying. /app/client/browser/controllers/postsController.js is 4 folders down. But with TextMate and CMD+T, it shouldn't be an issue.

You could also have this structure if you only had 1 client (or just a default client):

|-- app
|   |-- controllers
|   |-- models
|   |-- views
|   `-- client
|       |-- controllers
|       |-- models
|       `-- views

That's pretty clear, and it lends itself to agile development really well.

My vote: ✔

3: More top-level folders

|-- app
|   |-- controllers
|   |-- models
|   |-- views
|-- browser
|   |-- controllers
|   |-- models
|   |-- views
|-- mobile
|   |-- controllers
|   |-- models
|   |-- views
`-- config
`-- lib
`-- spec
`-- vendor

Pros:

  • Minimum folder nesting
  • model/view/controller folders are all at the same level

Cons:

  • Having multiple top-level folders, all of which are mvc code, is not conceptually clear. They should be part of one directory (taking us back to #2). Having every folder at the top level be a completely conceptually distinct part of the app (database vs. app vs. config vs. tests) is a clarifying convention.

My vote: second choice, but no

4: Namespaces inside /app

|-- app
|   `-- client
|       |-- controllers
|       |-- models
|       |-- views
|   `-- mobile
|       |-- controllers
|       |-- models
|       |-- views
|   `-- server
|       |-- controllers
|       |-- models
|       |-- views
`-- config
`-- lib
`-- spec
`-- vendor

Pros:

  • Clear, normalized separation of concerns. Everything fits into the same folder structure, instead of having the "default" stuff in /app, and then also nesting components in there.

Cons:

  • For the simple case, you have to create a nested folder.
    • Counterargument: But, you're setup to easily add other clients for the app
  • By not having the default code go in the top level /app, it's not as clear that server code can be used on the client (e.g. using /app/server/models/user.js on the client. it makes sense if it's in /app/models/user.js however.).

My vote: no

5: Top-level /client and /server directories

This breaks convention, but it's an option. Rename /app to /server

|-- client
|   |-- controllers
|   |-- models
|   |-- views
|-- server
|   |-- controllers
|   |-- models
|   |-- views
`-- config
`-- lib
`-- spec
`-- vendor

Pros:

  • Clear: there is a client and server app.

Cons:

  • If you had multiple client apps (browser, mobile, ipad, etc.), you'd end up doing things like #2 or #3.

My vote: no

Which do you prefer?

I prefer folder structure #2.

@demisx
Copy link

demisx commented Sep 18, 2017

+1 for @emadb's organization. Feature based structure is the way to go.

@inancgumus
Copy link

@rocketspacer That means, there's a new concept waiting to go into its own package. And then, separate the dependencies via abstractions.

@rkt2spc
Copy link

rkt2spc commented Jan 30, 2018

@mareksuscak @inancgumus I can't really make a solid project structure out of a vague emerging concept simply because I don't know how to properly name it. How common is common, what should I call the abstraction of login and transaction?
We decided to adopt Microservices and solve this problem at a different level now.

@alamenai
Copy link

@lancejpollard ,what we put in 'spec' folder ?

@nbaua
Copy link

nbaua commented Mar 13, 2019

@lancejpollard ,what we put in 'spec' folder ?

Test cases

@bomzj
Copy link

bomzj commented May 8, 2019

Feature Folders is the way to go for any size of project!

@danmandel
Copy link

I don't think there's any optimal answer between grouping by function vs grouping by feature, it seems to just come down to personal preference. It would be nice if there was an IDE setting or global tool that devs could install to make swapping between folder structures as easy as a 1-line change in a config file.

@mytharcher
Copy link

mytharcher commented Sep 9, 2019

My principal:

  • Any folder should match the concept of dimension, so /<feature> and /test should not be placed under same folder.
  • Node.js project should not combine both client and server codes, unless you need SSR, so I will not need to concern about the mixed project folders.

And my further consideration is that sometime (I can say more than half) my services code can't always match to the model (database tables) / controller (routes). Because controller sometimes needs to handle webhooks which not match to model, and services may also for third-party integration logics. So I prefer the function rather than feature.

While the architecture will evolve into micro services in future, function layer first will not become more complex.

Something I am confused is when I divide the function, how my main app logic folder should be named? Like src / lib / main / app? Another confusion is should I just place the main logic layer folders under project root? Such as controllers / services / model / test ... etc.

I have read about the guideline of golang project layout, and agreed with their idea about the /src:

Some Go projects do have a src folder, but it usually happens when the devs came from the Java world where it's a common pattern. If you can help yourself try not to adopt this Java pattern. You really don't want your Go code or Go projects to look like Java :-)

So my practice now has been summarized into a repository here: express-bootstrap. Any discussion or idea will be welcome.

@lancejpollard
Copy link
Author

Here is my current system.

@vish9812
Copy link

vish9812 commented Feb 28, 2020

Feature based structure seems the way to go!

Here is my app

|--src 
|  |--core  
|  |  |--orders
|  |  |--basket
|  |  |--common
|  |--infrastructure
|  |  |--auth/
|  |  |--logger/
|  |--utils
|  |  |--config
|  |  |--crypto
| --package.json
| --index.js
| --README.md

@nashid
Copy link

nashid commented Jun 24, 2020

@Vishch - you don't give a clear separation of tests. All the tests go to the tests folder?

@vish9812
Copy link

vish9812 commented Jun 25, 2020

@nashid yes the tests should go in their respective feature folders

@vikrantsingh47
Copy link

@nashid yes the tests should go in their respective feature folders

should the routes also go in their respective feature folders?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment