Express: How to pass app-instance to routes from a different file?


Question

I want to split up my routes into different files, where one file contains all routes and the other one the corresponding actions. I currently have a solution to achieve this, however I need to make the app-instance global to be able to access it in the actions. My current setup looks like this:

app.js:

var express   = require('express');
var app       = express.createServer();
var routes    = require('./routes');

var controllers = require('./controllers');
routes.setup(app, controllers);

app.listen(3000, function() {
  console.log('Application is listening on port 3000');
});

routes.js:

exports.setup = function(app, controllers) {

  app.get('/', controllers.index);
  app.get('/posts', controllers.posts.index);
  app.get('/posts/:post', controllers.posts.show);
  // etc.

};

controllers/index.js:

exports.posts = require('./posts');

exports.index = function(req, res) {
  // code
};

controllers/posts.js:

exports.index = function(req, res) {
  // code
};

exports.show = function(req, res) {
  // code
};

However, this setup has a big issue: I have a database- and an app-instance I need to pass to the actions (controllers/*.js). The only option I could think of, is making both variables global which isn't really a solution. I want to separate routes from the actions because I have a lot of routes and want them in a central place.

What's the best way to pass variables to the actions but separate the actions from the routes?

1
98
4/10/2012 2:11:59 PM

Accepted Answer

Node.js supports circular dependencies.
Making use of circular dependencies instead of require('./routes')(app) cleans up a lot of code and makes each module less interdependent on its loading file:


app.js

var app = module.exports = express(); //now app.js can be required to bring app into any file

//some app/middleware setup, etc, including 
app.use(app.router);

require('./routes'); //module.exports must be defined before this line


routes/index.js

var app = require('../app');

app.get('/', function(req, res, next) {
  res.render('index');
});

//require in some other route files...each of which requires app independently
require('./user');
require('./blog');


-----04/2014 update-----
Express 4.0 fixed the usecase for defining routes by adding an express.router() method!
documentation - http://expressjs.com/4x/api.html#router

Example from their new generator:
Writing the route:
https://github.com/expressjs/generator/blob/master/templates/js/routes/index.js
Adding/namespacing it to the app: https://github.com/expressjs/generator/blob/master/templates/js/app.js#L24

There are still usecases for accessing app from other resources, so circular dependencies are still a valid solution.

97
5/12/2015 7:25:31 AM

Use req.app, req.app.get('somekey')

The application variable created by calling express() is set on the request and response objects.

See: https://github.com/visionmedia/express/blob/76147c78a15904d4e4e469095a29d1bec9775ab6/lib/express.js#L34-L35


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon