[node.js] ExpressJS How to structure an application?

I'm using the ExpressJS web framework for NodeJS.

People using ExpressJS put their environments (development, production, test...), their routes etc on the app.js. I think that it's not a beautiful way because when you have a big application, app.js is too big!

I would like to have this directory structure:

| my-application
| -- app.js
| -- config/
     | -- environment.js
     | -- routes.js

Here's my code:

app.js

var express = require('express');
var app = module.exports = express.createServer();

require('./config/environment.js')(app, express);
require('./config/routes.js')(app);

app.listen(3000);

config/environment.js

module.exports = function(app, express){
    app.configure(function() {
    app.use(express.logger());
    });

    app.configure('development', function() {
    app.use(express.errorHandler({
        dumpExceptions: true,
        showStack: true
    }));
    });

    app.configure('production', function() {
    app.use(express.errorHandler());
    });
};

config/routes.js

module.exports = function(app) {
    app.get('/', function(req, res) {
    res.send('Hello world !');
    });
};

My code works well and I think that the structure of the directories is beautiful. However, the code had to be adapted and I'm not sure that it's good/beautiful.

Is it better to use my structure of directories and adapt the code or simply use one file (app.js)?

Thanks for your advices!

This question is related to node.js express

The answer is


Well I put my routes as a json file, that I read at the beginning, and in a for-loop in app.js set up the routes. The route.json includes which view that should be called, and the key for the values that will be sent into the route.
This works for many simple cases, but I had to manually create some routes for special cases.


I am giving MVC style folder structure please find bellow .

We used bellow folder structure for our big and medium web applications .

 myapp   
|
|
|____app
|      |____controllers
|      |    |____home.js
|      |
|      |____models
|      |     |___home.js
|      |
|      |____views
|           |___404.ejs
|           |___error.ejs
|           |___index.ejs
|           |___login.ejs
|           |___signup.ejs
|   
|
|_____config
|     |___auth.js
|     |___constants.js
|     |___database.js
|     |___passport.js
|     |___routes.js
|
|
|____lib
|    |___email.js
|
|____node_modules
|
|
|____public.js
|    |____css
|    |    |__style.css
|    |    
|    |____js
|    |    |__script.js
|    |
|    |____img
|    |    |__img.jpg
|    |
|    |
|    |____uploads
|         |__img.jpg
|      
|   
|
|_____app.js
|
|
|
|_____package.json

I have created one npm module for generation express mvc folder structurer.

Please find the bellow https://www.npmjs.com/package/express-mvc-generator

Just simple steps to generate and use this modules .

i) install module npm install express-mvc-generator -g

ii) check options express -h

iii) Generate express mvc structure express myapp

iv) Install dependencies: npm install:

v)Open your config/database.js , Please configure your mongo db.

vi)Run the application node app or nodemon app

vii)Check URL http://localhost:8042/signup OR http://yourip:8042/signup


My structure express 4. https://github.com/odirleiborgert/borgert-express-boilerplate

Packages

View engine: twig
Security: helmet
Flash: express-flash
Session: express-session
Encrypt: bcryptjs
Modules: express-load
Database: MongoDB
    ORM: Mongoose
    Mongoose Paginate
    Mongoose Validator
Logs: winston + winston-daily-rotate-file
Nodemon
CSS: stylus
Eslint + Husky

Structure

|-- app
    |-- controllers
    |-- helpers
    |-- middlewares
    |-- models
    |-- routes
    |-- services
|-- bin
|-- logs
|-- node_modules
|-- public
    |-- components
    |-- images
    |-- javascripts
    |-- stylesheets
|-- views
|-- .env
|-- .env-example
|-- app.js
|-- README.md

1) Your Express project filesystem maybe like:

/ ...
/lib
/node_modules
/public
/views
      app.js
      config.json
      package.json

app.js - you global app container

2) Module main file (lib/mymodule/index.js):

var express = require('express');    
var app = module.exports = express();
// and load module dependencies ...  

// this place to set module settings
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');

// then do module staff    
app.get('/mymodule/route/',function(req,res){ res.send('module works!') });

3) Connect module in main app.js

...
var mymodule = require('mymodule');
app.use(mymodule);

4) Sample logic

lib/login
lib/db
lib/config
lib/users
lib/verify
lib/
   /api/ 
   ...
lib/
   /admin/
      /users/
      /settings/
      /groups/
...
  • Best for testing
  • Best for scale
  • Separate depends by module
  • Grouping route by functionality (or modules)

tj says/show on Vimeo interesting idea how modularize express application - Modular web applications with Node.js and Express. Powerful and simple.


UPDATE (2013-10-29): Please see my other answer as well which has JavaScript instead of CoffeeScript by popular demand as well as a boilerplate github repo and an extensive README detailing my latest recommendations on this topic.

Config

What you are doing is fine. I like to have my own config namespace set up in a top-level config.coffee file with a nested namespace like this.

#Set the current environment to true in the env object
currentEnv = process.env.NODE_ENV or 'development'
exports.appName = "MyApp"
exports.env =
  production: false
  staging: false
  test: false
  development: false
exports.env[currentEnv] = true
exports.log =
  path: __dirname + "/var/log/app_#{currentEnv}.log"
exports.server =
  port: 9600
  #In staging and production, listen loopback. nginx listens on the network.
  ip: '127.0.0.1'
if currentEnv not in ['production', 'staging']
  exports.enableTests = true
  #Listen on all IPs in dev/test (for testing from other machines)
  exports.server.ip = '0.0.0.0'
exports.db =
  URL: "mongodb://localhost:27017/#{exports.appName.toLowerCase()}_#{currentEnv}"

This is friendly for sysadmin editing. Then when I need something, like the DB connection info, it`s

require('./config').db.URL

Routes/Controllers

I like to leave my routes with my controllers and organize them in an app/controllers subdirectory. Then I can load them up and let them add whatever routes they need.

In my app/server.coffee coffeescript file I do:

[
  'api'
  'authorization'
  'authentication'
  'domains'
  'users'
  'stylesheets'
  'javascripts'
  'tests'
  'sales'
].map (controllerName) ->
  controller = require './controllers/' + controllerName
  controller.setup app

So I have files like:

app/controllers/api.coffee
app/controllers/authorization.coffee
app/controllers/authentication.coffee
app/controllers/domains.coffee

And for example in my domains controller, I have a setup function like this.

exports.setup = (app) ->
  controller = new exports.DomainController
  route = '/domains'
  app.post route, controller.create
  app.put route, api.needId
  app.delete route, api.needId
  route = '/domains/:id'
  app.put route, controller.loadDomain, controller.update
  app.del route, controller.loadDomain, exports.delete
  app.get route, controller.loadDomain, (req, res) ->
    res.sendJSON req.domain, status.OK

Views

Putting views in app/views is becoming the customary place. I lay it out like this.

app/views/layout.jade
app/views/about.jade
app/views/user/EditUser.jade
app/views/domain/EditDomain.jade

Static Files

Go in a public subdirectory.

Github/Semver/NPM

Put a README.md markdown file at your git repo root for github.

Put a package.json file with a semantic version number in your git repo root for NPM.


I have written a post exactly about this matter. It basically makes use of a routeRegistrar that iterates through files in the folder /controllers calling its function init. Function init takes the express app variable as a parameter so you can register your routes the way you want.

var fs = require("fs");
var express = require("express");
var app = express();

var controllersFolderPath = __dirname + "/controllers/";
fs.readdirSync(controllersFolderPath).forEach(function(controllerName){
    if(controllerName.indexOf("Controller.js") !== -1){
        var controller = require(controllersFolderPath + controllerName);
        controller.init(app);
    }
});

app.listen(3000);

I think it's a great way to do it. Not limited to express but I've seen quite a number of node.js projects on github doing the same thing. They take out the configuration parameters + smaller modules (in some cases every URI) are factored in separate files.

I would recommend going through express-specific projects on github to get an idea. IMO the way you are doing is correct.


This may be of interest:

https://github.com/flatiron/nconf

Hierarchical node.js configuration with files, environment variables, command-line arguments, and atomic object merging.


This is how most of my express project directory structure looks.

I usually do a express dirname to initialise the project, forgive my laziness, but it's very flexible and extendable. PS - you need to get express-generator for that (for those who're looking for it sudo npm install -g express-generator, sudo because you're installing it globally)

|-- bin
    |-- www //what we start with "forever"
|-- bower_components
|-- models
    |-- database.js
    |-- model1.js //not this exact name ofcourse.
    |-- .
|-- node_modules
|-- public
    |-- images
    |-- javascripts
        |-- controllers
        |-- directives
        |-- services
        |-- app.js
        |-- init.js //contains config and used for initializing everything, I work with angular a lot.
    |-- stylesheets
|-- routes
    |-- some
    |-- hierarchy
    .
    .
|-- views
    |-- partials
    |-- content
|-- .env
|-- .env.template
|-- app.js
|-- README.md

You must be wondering why .env files? Because they work! I use dotenv module in my projects (a lot recently) and it works! Pop in these 2 statements in app.js or www

var dotenv = require('dotenv');
dotenv.config({path: path.join(__dirname + "/.env")});

And another line to quickly set /bower_components to serve static content under the resource /ext

app.use('/ext', express.static(path.join(__dirname, 'bower_components')));

It probably can be a fit for people who're looking to use Express and Angular together, or just express without that javascripts hierarchy of course.


I recently embraced modules as independent mini-apps.

|-- src
  |--module1
  |--module2
     |--www
       |--img
       |--js
       |--css
     |--#.js
     |--index.ejs
  |--module3
  |--www
     |--bower_components
     |--img
     |--js
     |--css
  |--#.js
  |--header.ejs
  |--index.ejs
  |--footer.ejs

Now for any module routing (#.js), views (*.ejs), js, css and assets are next to each other. submodule routing is set up in the parent #.js with two additional lines

router.use('/module2', opt_middleware_check, require('./module2/#'));
router.use(express.static(path.join(__dirname, 'www')));

This way even subsubmodules are possible.

Don't forget to set view to the src directory

app.set('views', path.join(__dirname, 'src'));

A simple way to structure ur express app:

  • In main index.js the following order should be maintained.

    all app.set should be first.

    all app.use should be second.

    followed by other apis with their functions or route-continue in other files

    Exapmle

    app.use("/password", passwordApi);

    app.use("/user", userApi);

    app.post("/token", passport.createToken);

    app.post("/logout", passport.logout)


My question was introduced in April 2011, it's quiet old. During this time, I could improve my experience with Express.js and how to architecture an application written using this library. So, I share here my experience.

Here's my directory structure:

+-- app.js   // main entry
+-- config   // The configuration of my applications (logger, global config, ...)
+-- models   // The model data (e.g. Mongoose model)
+-- public   // The public directory (client-side code)
+-- routes   // The route definitions and implementations
+-- services // The standalone services (Database service, Email service, ...)
+-- views    // The view rendered by the server to the client (e.g. Jade, EJS, ...)

App.js

The goal of the app.js file is to bootstrap the expressjs application. It loads the configuration module, the logger module, wait for database connection, ..., and run the express server.

'use strict';
require('./config');
var database = require('./services/database');
var express = require('express');
var app = express();
module.exports = app;

function main() {
  var http = require('http');

  // Configure the application.
  app.configure(function () {
    // ... ... ...
  });
  app.configure('production', function () {
    // ... ... ...
  });
  app.configure('development', function () {
    // ... ... ...
  });

  var server = http.createServer(app);

  // Load all routes.
  require('./routes')(app);

  // Listen on http port.
  server.listen(3000);
}

database.connect(function (err) {
  if (err) { 
    // ...
  }
  main();
});

routes/

The routes directory has a index.js file. Its goal is to introduce a kind of magic to load all other files inside the routes/ directory. Here's the implementation:

/**
 * This module loads dynamically all routes modules located in the routes/
 * directory.
 */
'use strict';
var fs = require('fs');
var path = require('path');

module.exports = function (app) {
  fs.readdirSync('./routes').forEach(function (file) {
    // Avoid to read this current file.
    if (file === path.basename(__filename)) { return; }

    // Load the route file.
    require('./' + file)(app);
  });
};

With that module, creating a new route definition and implementation is really easy. For examples, hello.js:

function hello(req, res) {
  res.send('Hello world');
}

module.exports = function (app) {
  app.get('/api/hello_world', hello);
};

Each route module is standalone.


Sails.js structure looks nice and clean to me, so I use MVC style structure for my express projects, similar to sails.js.

project_root  
|  
|_ _ app  
|_ _ |_ _ controllers  
|_ _ |_ _ |_ _ UserController.js  
|_ _ |_ _ middlewares  
|_ _ |_ _ |_ _ error.js  
|_ _ |_ _ |_ _ logger.js  
|_ _ |_ _ models  
|_ _ |_ _ |_ _ User.js  
|_ _ |_ _ services  
|_ _ |_ _ |_ _ DatabaseService.js  
|  
|_ _ config  
|_ _ |_ _ constants.js  
|_ _ |_ _ index.js  
|_ _ |_ _ routes.js  
|  
|_ _ public  
|_ _ |_ _ css  
|_ _ |_ _ images  
|_ _ |_ _ js  
|  
|_ _ views  
|_ _ |_ _ user  
|_ _ |_ _ |_ _ index.ejs  

App folder - contains overall login for application.
Config folder - contains app configurations, constants, routes.
Public folder - contains styles, images, scripts etc.
Views folder - contains views for each model (if any)

Boilerplate project could be found here,
https://github.com/abdulmoiz251/node-express-rest-api-boilerplate


I don't think it's a good approach to add routes to config. A better structure could be something like this:

application/
| - app.js
| - config.js
| - public/ (assets - js, css, images)
| - views/ (all your views files)
| - libraries/ (you can also call it modules/ or routes/)
    | - users.js
    | - products.js
    | - etc...

So products.js and users.js will contain all your routes will all logic within.


It's been quite a while since the last answer to this question and Express has also recently released version 4, which added a few useful things for organising your app structure.

Below is a long up to date blog post about best practices on how to structure your Express app. http://www.terlici.com/2014/08/25/best-practices-express-structure.html

There is also a GitHub repository applying the advice in the article. It is always up to date with the latest Express version.
https://github.com/terlici/base-express


it is now End of 2015 and after developing my structure for 3 years and in small and large projects. Conclusion?

Do not do one large MVC, but separate it in modules

So...

Why?

  • Usually one works on one module (e.g. Products), which you can change independently.

  • You are able to reuse modules

  • You are able to test it separatly

  • You are able to replace it separatly

  • They have clear (stable) interfaces

    -At latest, if there were multiple developers working, module separation helps

The nodebootstrap project has a similar approach to my final structure. (github)

How does this structure look like?

  1. Small, capsulated modules, each with separate MVC

  2. Each module has a package.json

  3. Testing as a part of the structure (in each module)

  4. Global configuration, libraries and Services

  5. Integrated Docker, Cluster, forever

Folderoverview (see lib folder for modules):

nodebootstrap structure


Best Way To MVC Structure for ExpressJs Project with handlebar & Passportjs

- app
      -config 
        -passport-setup.js
      -controllers
      -middleware
      -models
      -routes
      -service
    -bin
      -www
      -configuration.js
      -passport.js
    -node_modules
    -views
     -handlebars page
    -env
    -.gitignore
    -package.json
    -package-lock.json

The following is Peter Lyons' answer verbatim, ported over to vanilla JS from Coffeescript, as requested by several others. Peter's answer is very able, and anyone voting on my answer should vote on his as well.


Config

What you are doing is fine. I like to have my own config namespace set up in a top-level config.js file with a nested namespace like this.

// Set the current environment to true in the env object
var currentEnv = process.env.NODE_ENV || 'development';
exports.appName = "MyApp";
exports.env = {
  production: false,
  staging: false,
  test: false,
  development: false
};  
exports.env[currentEnv] = true;
exports.log = {
  path: __dirname + "/var/log/app_#{currentEnv}.log"
};  
exports.server = {
  port: 9600,
  // In staging and production, listen loopback. nginx listens on the network.
  ip: '127.0.0.1'
};  
if (currentEnv != 'production' && currentEnv != 'staging') {
  exports.enableTests = true;
  // Listen on all IPs in dev/test (for testing from other machines)
  exports.server.ip = '0.0.0.0';
};
exports.db {
  URL: "mongodb://localhost:27017/#{exports.appName.toLowerCase()}_#{currentEnv}"
};

This is friendly for sysadmin editing. Then when I need something, like the DB connection info, it`s

require('./config').db.URL

Routes/Controllers

I like to leave my routes with my controllers and organize them in an app/controllers subdirectory. Then I can load them up and let them add whatever routes they need.

In my app/server.js javascript file I do:

[
  'api',
  'authorization',
  'authentication',
  'domains',
  'users',
  'stylesheets',
  'javascripts',
  'tests',
  'sales'
].map(function(controllerName){
  var controller = require('./controllers/' + controllerName);
  controller.setup(app);
});

So I have files like:

app/controllers/api.js
app/controllers/authorization.js
app/controllers/authentication.js
app/controllers/domains.js

And for example in my domains controller, I have a setup function like this.

exports.setup = function(app) {
  var controller = new exports.DomainController();
  var route = '/domains';
  app.post(route, controller.create);
  app.put(route, api.needId);
  app.delete(route, api.needId);
  route = '/domains/:id';
  app.put(route, controller.loadDomain, controller.update);
  app.del(route, controller.loadDomain, function(req, res){
    res.sendJSON(req.domain, status.OK);
  });
}

Views

Putting views in app/views is becoming the customary place. I lay it out like this.

app/views/layout.jade
app/views/about.jade
app/views/user/EditUser.jade
app/views/domain/EditDomain.jade

Static Files

Go in a public subdirectory.

Github/Semver/NPM

Put a README.md markdown file at your git repo root for github.

Put a package.json file with a semantic version number in your git repo root for NPM.


http://locomotivejs.org/ provides a way to structure an app built with Node.js and Express.

From the website:

"Locomotive is a web framework for Node.js. Locomotive supports MVC patterns, RESTful routes, and convention over configuration, while integrating seamlessly with any database and template engine. Locomotive builds on Express, preserving the power and simplicity you've come to expect from Node."


I like to use a global "app", rather than exporting a function etc


Examples related to node.js

Hide Signs that Meteor.js was Used Querying date field in MongoDB with Mongoose SyntaxError: Cannot use import statement outside a module Server Discovery And Monitoring engine is deprecated How to fix ReferenceError: primordials is not defined in node UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.62.dylib error running php after installing node with brew on Mac internal/modules/cjs/loader.js:582 throw err DeprecationWarning: Buffer() is deprecated due to security and usability issues when I move my script to another server Please run `npm cache clean`

Examples related to express

UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block jwt check if token expired Avoid "current URL string parser is deprecated" warning by setting useNewUrlParser to true MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017] npm notice created a lockfile as package-lock.json. You should commit this file Make Axios send cookies in its requests automatically What does body-parser do with express? SyntaxError: Unexpected token function - Async Await Nodejs Route.get() requires callback functions but got a "object Undefined" How to redirect to another page in node.js