NodeJS and Express - separate my controllers and models - javascript

I'm building my first Express app. It's a bit messy as my controllers and my models are all in the same place: the app.js file.
Is there a way that I can separate those?
Even artificially, by creating different files and then using some third party program to compile them into the app.js file.

First of all, you need to create your controllers and model folders.
You can use a module called express-load which can be used to autoload models, routes, schemas, configs, controllers, object maps... etc...
in your main file, mine is called app.js you load them right before start the server code line.. it should look like
//requires....
var load = require('express-load');
//your code
load('models')
.then('controllers')
.then('routes')
.into(app);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express listening on port "+ app.get('port'));
});
module.exports = app;
Then, your view folder you can create folders to keep your code organized, then subfolders, I created a folder called home, and inside of it my index view.
In my controllers folder I created a js file called home.js, and which will look for my index view:
module.exports = function(app){
var HomeController = {
index: function(req, res){
res.render('home/index');
}
};
return HomeController;
}
At last in your routes folder, you can set your application routes, each view needs to be specified in your controller. My file for routes its called home.js
module.exports = function(app){
var home = app.controllers.home;
app.get('/', home.index);
}

What I generally do it is to write a module which contains all the routes definition and load it in app.js e.g
require('./routes')(app);
My ./routes.js generally looks like this
module.exports = function (app) {
log.info('Loading express routes...');
/* registration */
app.post('/users', require('./routes/register-users')); // register user
app.post('/agents', require('./routes/register-agents')); // register agents
};
and I keep all the routes (.js) files inside a directory call routes
Hope it is what you are looking for.

Is there a way that I can separate those?
Yes, and you should separate them.
What most people do is declare the routes in the main app.js file and include separate files for the controllers (just like Rituparna described).
Those controllers files will in turn very likely include your model files via a require. For example.
In app.js
var blogRoutes = require('./routes/blogRoutes');
app.get('/api/blog/all', blogRoutes.all);
In routes\blogRoutes.js
var model = require('../models/blogModel');
var all = function(req, res) {
// your controller logic
// and very likely calls to your model
var m = model.blog(whatever);
res.send(m.something());
};
module.exports = {
all: all
}
In models\blogModel.js
var something = function() {
return "something";
};
module.exports = {
something: something
}
You can see a working version of this in this repo https://github.com/hectorcorrea/hectorcorrea.com

You should checkout the examples from the Express Github repo, there are multiple ways to do this (based on personal preference):
https://github.com/visionmedia/express/tree/master/examples/mvc
https://github.com/visionmedia/express/blob/master/examples/resource/app.js
https://github.com/visionmedia/express/tree/master/examples/route-separation

There are some examples here that may help you..
Route Separation: https://github.com/visionmedia/express/tree/master/examples/route-separation
MVP: https://github.com/visionmedia/express/tree/master/examples/mvc

Related

Express.js returning multiple routes in a single exported router object returns incorrect route

I am trying to utilize an MVC pattern for express. I am modularizing routes and trying to declare the express router in only the server entry file and nowhere else.
My current issue is when exporting my appRoute function in my main routes file (see below), the first route (user route), returns users. I have another route called game that is exported in the same function but it still returns users instead of games.
Both routes have a controller function called getAll that gets different data from different tables.
If I try and visit the route: http://localhost:8000/user/getAll, it returns all users just fine.
If I try and visit the route: http://localhost:8000/game/getAll, it still returns all users even when they're different routes...
If I were to flip the order of users and games in the main routes file where game is first and user is second, users starts to return games. It's like the second route mimics the first route.
This may be something simple, but any help I will appreciate.
My code is as shown below
server entry point (index.js)
const app = express();
const router = express.Router();
const bootstrap = require('./src/bootstrap');
bootstrap(app, router);
I am passing on the app and router instance to my bootstrap file where all routes will be exported to.
bootstrap.js (this file gets all exported routes and uses them within the app)
const { appRoute } = require('./routes');
module.exports = (app, router) => {
return app.use('/', appRoute(router));
};
I am passing on the router instance to my main routes file where all routes are exported from.
Main routes file (index.js): this file requires all routes and uses them within the router instance. I think this might be where my issue is but I am a little stuck on how I might fix it.
const { userRoute } = require('./userRoute');
const { gameRoute } = require('./gameRoute');
exports.appRoute = (router) => {
router.use('/user', userRoute(router));
router.use('/game', gameRoute(router));
return router;
};
Game route files (index.js): returns all users instead of games
const { gameController } = require('../../controllers');
exports.gameRoute = (router) => {
return router.get('/getAll', gameController.getAll);
};
Any help is greatly appreciated. If there is any clarification needed please let me know.
I think you need to create a separate router for game and user.
See the express.Routing section and birds.js example here

How to access a configuration object throughout the entire application?

I have created a simple Node.js application, throughout which I use static route paths. So I need to know how to access an object without requesting in every route in my application.
Current method =>
routeLink.js
var routesMap = [{
createUserRoute: '/create-user',
route2: '/user-profile',
// ...
}];
createUserRoute.js
var routLinks = require('./config/routeLink');
module.exports = function(router){
router.post('/', function(req, res){
// do the task
res.redirect(routLinks.createUserRoute);
});
}
Just like you see in this example, I have to
require('./config/routeLink')
without using this how to I access routesMap from all of the Routers?
You have two option if you don't want to require your config in each route file:
1/ make your config global in your whole application ( not recommended )
2/ use environment variables, take a look at dotenv

Achieve best performance when passing variables through different node.js modules/files

In a node application it's common that you start loading some modules like this:
var express = require('express')
, app = express()
, mongodb = require('mongodb')
, http = require('http');
Now, let's say you have a routes.js file which looks like this:
module.exports = function(app) {
app.get('/', function(req, res) {
res.render('homepage');
});
// other routes
};
So when you call that routes.js file, you pass the app var:
require('./routes')(app);
My question is: what is happening there? Is there resource consumption when passing the app variable to the routes module? I know that node.js caches modules, but I would like to know how that affects variables passed between them and I wonder if the following approach is efficient:
Let's start loading some modules, but let's do in a different way:
var _ = {};
_.express = require('express');
_.app = _.express();
_.mongodb = require('mongodb');
_.http = require('http');
Routes.js:
module.exports = function(_) {
_.app.get('/', function(req, res) {
res.render('homepage');
});
// other routes
};
Call to routes.js:
require('./routes')(_);
Obviously the _ variable will be a large one, but it will include anything you may need in any module. So I wonder if the size of the passed variable affects performance, in which case it would be just stupid to pass more data than needed.
I seek for achieving the best achievable performance in my applications while I try to simplify things when writing code, so any advice that may help with this, or any explanation about how this works behind the scenes in node.js will be appreciated.
Thanks in advance.
See here.
tl;dr: objects are passed by reference, not by value. So you are not expanding your memory consumption when you pass the same object multiple times to multiple modules.

How to make object references available in Node modules?

I have an Express.js web app. In the main app.js file, I require() a bunch of third party dependencies. Recently I've started extracting parts of my app.js code into separate modules, e.g.
// in app.js
var users = require('./modules/users');
// and then e.g.
// users.add(doc);
Inside my modules, I sometimes need to use objects that are available in my main app.js file and I'm wondering what's the best way to pass references to those object to my modules.
My current approach:
// in app.js
// pass needed object references in initialization step
users.init([db, logger]);
and
// in modules/users.js
var db, logger;
exports.init = function (deps) {
db = deps[0];
logger = deps[1];
};
Does this approach make sense? Is there a better way to perform this?
Sure, just use modules! :)
// db.js
// create db instance here rather than in app.js
module.exports = db;
And
// logger.js
// create logger instance here rather than in app.js
module.exports = logger;
Then
// app.js
var db = require('./db');
And
// lib/somewhere.js
var db = require('../db');
This way you're able to rely on the CommonJS dependency injection system rather than on doing the dependency injection all by yourself (passing references around instead of requireing a module into yours).
The reason why this works as expected is that modules are only interpreted once, so if you instantiate everything once as opposed to using a factory function, it just works.
You should just be able to require modules as normal:
// users.js
var db = require('./db');
exports.init = function() {
// use db in here
};
However, sometimes this isn't possible and you will need to explicitly pass in the module.
One way to do it is to pass in dependencies when you require the module:
// users.js
module.exports = function(db, logger) {
return {
init: function() { /* use db and logger in here */}
};
}
// app.js
var db = ...;
var logger = ...;
var users = require('./users')(db, logger);
users.init();
This is the pattern that I personally prefer, I think it's cleaner to pass dependencies into the require than into some init method like you have in your example.
You'll see this done in ExpressJS code quite a lot, for example when we have all our routes in another file and need to pass our app instance around:
require('./routes')(app);
If you need something to be initialized specifically in app.js rather than their own module you can export them from app.js and then require app.js:
// app.js
var db = require("db"),
logger = require("logger");
// do your initialization with db and logger
module.exports = { db: db, logger: logger };
and then:
// users.js
var db = require("./app").db,
logger = require("./app").logger;
// use db and logger
This works because as #Nico mentioned, modules are interpreted once and app.js will not be interpreted each time it is required from elsewhere.

How can I do my routing without having one long file of all the routes in nodejs?

Using this link as a reference https://github.com/visionmedia/express/tree/master/examples/route-separation to what "could be done"
I AM NOT USING EXPRESS. I AM USING THEM AS AN EXAMPLE.
I want to do something like this but "simpler" ...
How can I get away from declaring all my routes in one long, complex list all in one file? Can I define them by passing a router into my modules, and then including all the code in one directory ... ok, I'll suffer having one long document that only does "require" includes, like an index.js, for this one ~ at least that one my build scripts can rebuild for me, but preferably not in my primary file for every single route that I may add.
So for instance, they use this code:
// General
app.get('/', site.index);
// User
app.all('/users', user.list);
app.all('/user/:id/:op?', user.load);
app.get('/user/:id', user.view);
app.get('/user/:id/view', user.view);
app.get('/user/:id/edit', user.edit);
app.put('/user/:id/edit', user.update);
// Posts
app.get('/posts', post.list);
I want to avoid making a list like that in my app.js. I want instead to have each file know what the routes are for that file.
Here's what I'm wanting to do: (please don't critique the code, I'm making it very simple so I make sure that I am illustrating my code the way I want to do it)
//app.js
var router = require('./myRouter.js')
var includes = require('./routes/*.js').register(router)
// do some stuff here with an https server and start the server here
and
//./routes/user.js
var myRouter;
exports.register(router){
myRouter = router;
}
router.addRoute(/* here I do the magic associated with this route */)
Can I do it just that simply? What am I missing here?
I haven't written this code because I'm just ever so certain that I'm going about this the wrong way.
And if I am going to have to use something like an index.js in the /routes/ folder, can I use that same concept that I demonstrated I would like to use in my code of .register(router) appended so I can pass that information down recursively? Would that work?
I use an index.js file for this and use require("routes") which is a folder.
// app.js
route = require("./routes"),
...
route(app);
// routes/index.js
var index = require("./index-route"),
about = require("./about-route"),
posts = require("./posts-route");
module.exports = function(app) {
index(app);
about(app);
posts(app);
};
This works because if you require a folder it will load index.js by default.
If you have a lot of routes you might want to load them based on convention
var routes = [];
// read all files
fs.readdir("./", function(files) {
files.forEach(function(val) {
// require all non-index.js files.
if (val !== "index.js") {
routes.push(require(val));
}
});
});
module.exports = function(app) {
// for each route you required call it with app.
routes.forEach(val.bind(null, app));
}
This would load all .js files that are not "index.js", so any file in your /routes/ folder would be loaded and run when you route them.
Your solution looks vaguely like you wish to use the Visitor Patern, in which case I suggest you make ./roots/ require-able (see this question) and in index.js you include all the files you wish (as local's) and export a register module which calls the register module on each of the required files.
Or you could copy the code from the above answer directly into your main file.

Categories

Resources