How to organize large Node.js projects

node.js

node.js Problem Overview


What are some good ways to organize large Node.js projects?

For example, an app making use of both express.js and socket.io? This would include both application logical structure as well as filesystem.

Currently, I'm finding myself shoving a ton of code into a single master js file and placing code into a giant global object, and it feels naughty.

node.js Solutions


Solution 1 - node.js

A Beginners Example

I like the originally checked from @david-ellis and you should study it in depth to understand it as it is a good one. However, I would have liked it more simplified for the beginners wanting to see a straight forward example. Here's what I would have liked to have seen someone show me.

Let's give a typical scenario where you are using express and you have a lot of routes listed on your app.js file. Its contents would look something like this:

app.js

// ... startup code omitted above

app.get('/', function(req, res) {
  res.render('index', { title : 'home' });
});
app.get('/contactus', function(req, res) {
  res.render('contactus', { title : 'contact us' });
});
app.get('/anotherpage', function(req, res) {
  res.render('anotherpage', { title : 'another page' });
});
// and so on...

You can imagine if you have 50 routes, this file can get quite out of hand. It would be nice to remove some of this clutter out of the app.js file.

What you would do is create a "controllers" folder in your app so your structure would now look like this:

app.js
/controllers

Create a file within "/controllers" named "index.js" then put the following code.

/controllers/index.js

module.exports.set = function(app) {
   // copy your routes listed in your app.js directly into here
}

Cut and paste your route listings from your "app.js" file and place them into the "/controllers/index.js" file.

On your app.js file, remove your routes and in place of them do the following.

app.js

// remove your routes and replace with this code
var controllers = require('./controllers');
controllers.set(app);

Now if you wanted to have your "/controllers/index.js" file also be split up, let's add one more example so you can see how Node.js really acts like a Russian Doll in how its code can be organized.

Within "/controllers" add one more file "accounts.js" and place the following within it.

/controllers/account.js

module.exports.set = function(app) {
    // put more app route listings here
}

Now within your "/controllers/index.js file, put a reference to "account.js"

/controllers/index.js

var account = require('./account.js');

module.exports.set = function(app) {
   // your routes here

   // let "account.js" set other routes
   account.set(app);
}

As you can imagine, you can keep breaking things up into smaller and smaller parts and put more folders within folders and reference with "require" if you like. You can use the same concept for "/lib" or library files. "node_modules" is already doing this.

That is just one of many reasons node.js is very enjoyable to program with.

Manageable Express 4 Routing example

Here's another post I responded to about express 4 routes that relates to this.

https://stackoverflow.com/questions/25260818/rest-with-express-js-nested-router/30549313#30549313

Solution 2 - node.js

I wrote a blog post about this very subject a few days ago, and although the article is in French, I set up a GitHub repo (in English) to show a working example of the structure I use.

Obviously, there is no definitive answer to this question, but it's interesting to see what others are doing, and I am all ears for other opinions on the subject (which was also discussed here, where you can see a summary of what I suggest).

Solution 3 - node.js

Similar to the other blog post, I wrote one specifically about organizing Express applications. It's the method I've been using for about a year and a half. Basically, organize your applications around your data entities or any other core elements. Place logic for each of those elements in their own directories. I tried to borrow a lot from Python.

http://rycole.com/2013/01/28/organizing-nodejs-express.html

Solution 4 - node.js

His Articles are no longer online, but Eric Satterwhite's node series recommended a structure as listed below.

# Project 
. 
|-- packages/
|   |-- project-core
|   |   |-- lib/
|   |   |-- commands/
|   |   |-- startup/
|   |   |-- conf/
|   |   |-- test/
|   |   |-- package.json
|   |   |-- README.md
|   |   |-- events.js
|   |   |-- .npmignore
|   |   `-- index.js
|-- package.json
`-- index.js

With the packages/ folder turning into your source for modularity.

Solution 5 - node.js

If you are a beginner in this area, I suggest you take a look at existing projects that are loved by developers. Some of them are:

  • Sails.js - 18k stars. You can take a look how they organized APP structure at the link I provided. A great website has an explanation for each folder in the structure.

  • Express.js generator - 800 stars. There is the great and simple template to start working with Express.js. Here you can notice how they split routes from the app.

By the way, so many developers did your case before, and you can just fork it and upgrade.

  • Kioska. Look how they separate events into different files at the events/ folder.

  • Ballons.io 2.3k stars. Unfortunately, they have the whole socket server in one file but you can learn the whole structure of the app with node.js and socket.io

Solution 6 - node.js

If you don't mind, you can always learn typescript and go for https://nestjs.com/

If you want to stick with JS I strongly recommend to use onion architecture. The best practice is to keep separated business logic, controllers, even libraries (they should be wrapped inside of some classes / helpers) - just in case, if you will have to migrate to another library (different CSV parser etc.).

With onion architecture, you don't care from where requests comes from, there won't be a lot of changes to add even some message broker.

Also try this one https://en.wikipedia.org/wiki/Domain-driven_design

ESLint may help with proper project organization.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionThomas Hunter IIView Question on Stackoverflow
Solution 1 - node.jsKing FridayView Answer on Stackoverflow
Solution 2 - node.jsmnaView Answer on Stackoverflow
Solution 3 - node.jsRyanView Answer on Stackoverflow
Solution 4 - node.jsOlivercodesView Answer on Stackoverflow
Solution 5 - node.jsYevhenii HerasymchukView Answer on Stackoverflow
Solution 6 - node.jshejkeroooView Answer on Stackoverflow