Sandro Munda Sandro Munda - 6 months ago 37
Node.js Question

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!

Answer

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.

Comments