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 thi
Let's say that you have a folder named "contollers".
In your app.js you can put this code:
console.log("Loading controllers....");
var controllers = {};
var controllers_path = process.cwd() + '/controllers'
fs.readdirSync(controllers_path).forEach(function (file) {
if (file.indexOf('.js') != -1) {
controllers[file.split('.')[0]] = require(controllers_path + '/' + file)
}
});
console.log("Controllers loaded..............[ok]");
... and ...
router.get('/ping', controllers.ping.pinging);
in your controllers forlder you will have the file "ping.js" with this code:
exports.pinging = function(req, res, next){
console.log("ping ...");
}
And this is it....
Or just do that:
var app = req.app
inside the Middleware you are using for these routes. Like that:
router.use( (req,res,next) => {
app = req.app;
next();
});
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
Like I said in the comments, you can use a function as module.exports. A function is also an object, so you don't have to change your syntax.
app.js
var controllers = require('./controllers')({app: app});
controllers.js
module.exports = function(params)
{
return require('controllers/index')(params);
}
controllers/index.js
function controllers(params)
{
var app = params.app;
controllers.posts = require('./posts');
controllers.index = function(req, res) {
// code
};
}
module.exports = controllers;
// app.js
let db = ...; // your db object initialized
const contextMiddleware = (req, res, next) => {
req.db=db;
next();
};
app.use(contextMiddleware);
// routes.js It's just a mapping.
exports.routes = [
['/', controllers.index],
['/posts', controllers.posts.index],
['/posts/:post', controllers.posts.show]
];
// app.js
var { routes } = require('./routes');
routes.forEach(route => app.get(...route));
// You can customize this according to your own needs, like adding post request
The final app.js:
// app.js
var express = require('express');
var app = express.createServer();
let db = ...; // your db object initialized
const contextMiddleware = (req, res, next) => {
req.db=db;
next();
};
app.use(contextMiddleware);
var { routes } = require('./routes');
routes.forEach(route => app.get(...route));
app.listen(3000, function() {
console.log('Application is listening on port 3000');
});
Another version: you can customize this according to your own needs, like adding post request
// routes.js It's just a mapping.
let get = ({path, callback}) => ({app})=>{
app.get(path, callback);
}
let post = ({path, callback}) => ({app})=>{
app.post(path, callback);
}
let someFn = ({path, callback}) => ({app})=>{
// ...custom logic
app.get(path, callback);
}
exports.routes = [
get({path: '/', callback: controllers.index}),
post({path: '/posts', callback: controllers.posts.index}),
someFn({path: '/posts/:post', callback: controllers.posts.show}),
];
// app.js
var { routes } = require('./routes');
routes.forEach(route => route({app}));
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:
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
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');
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.