I am currently developping a website that is using a lot of routes.
At the beginning, all the routes were implemented in a same file...
To make the things clearer, I decided to create multiple files, in order to separate the routes... using the Router module.
For example, in my users.js file I have:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
and in my main app.js file :
app.use('/users', require('./routes/user');
This works perfectly but the thing is that I would like my 'users' route
to access some variables that have been declared into the app.js file, before the app.use(...)
I know I can use require and module.exports, but some variables must be declared in my app.js, only one time, and I must access them from the routes I include.
You can pass them as a configuration object. Also change your route, to a function that returns a route, this way it can take parameters.
module.exports = function (options) {
return function (req, res, next) {
// do your thing
// you have access to options variable as well
}
}
And in your main JS file, require the file and call it, and pass all you need.
app.use('/users', require('./routes/user')({
option1: 'value1',
option2: 'value2'
}));
For things like database connection, your models and other third party libraries, you don't need to pass them as a configuration object. It is a good practice to move them to external files as well and require them in your routes' file. You need to decouple as much as modules you can.
Just keep that in mind that require will load every module once, the rest of the time, it just returns the reference to previously loaded module. Take a look at this question for more info.
For a more global access, you make the variables you want to share global.For example
//app.js
GLOBAL.config = {}
It's best to use a separate file for you application config. For example
//config.js
module.exports = {logging:true}
and make it a global variable in your app.js file as follow
//app.js
GLOBAL.config = require('./config');
Now it will be available in your routing definition. For example
//routes/users.js
router.get('/', function(req, res, next) {
if(config.logAccess){
var accessTime = new Date();
console.log('access at '+accessTime.toTimeString());
}
res.send('respond with a resource');
});
Related
Let Me explain what I am working on .
I have included the express module in app.js .
Here I want to access this module in index.js , admin.js , gallery.js.
but I dont want to write the same code again in all over js file .
let me show you my scenario.
app.js has
var express = require('express');
index.js has
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
gallery.js has
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.render('gallery', { title: 'Gallery' });
});
module.exports = router;
Here var express = require('express'); is already present in app.js .
I want to reuse it from app.js instead of including in every file .
What I have tried so far
I made global in app.js , so that I can access it all over
global.express = require('express');
this code is working for me .
Is this the correct approach or any other way to do or including express module in all the js file is fine ?
You can export your files (not app.js assuming this is your entry point) as a function and pass your express module into those files
gallery.js
module.exports = function(app) {
/* GET users listing. */
app.get('/', function(req, res, next) {
res.render('gallery', { title: 'Gallery' });
});
}
app.js
var express = require('express')
var app = express();
var galleryRoute = require('./gallery');
// Routes
galleryRoute(app);
I have read some where to avoid using Global Variables because there are some cons of it here are few of them:
The first reason is that when you create a global variable, it exists
throughout the lifetime of the application. When a variable persists
through the lifetime of the app it means that it is there, in memory,
occupying resources while the app is running.
Second, traditionally using global variables can cause concurrency
issues. If multiple threads can access the same variable and there
are no access modifiers or failsafes in place, it can lead to some
serious issues of two threads attempting to access and use the same
variable. However, while this is the case in other languages, it is
not necessarily the case for Node.js as it is strictly a
single-threaded environment. While it is possible to cluster Node
processes, there is no native way to communicate between them.
The last reason I am going to talk about is that using globals can
cause implicit coupling between files or variables. Coupling is not a
good thing when it comes to writing great code. When writing code, we
want to make sure that it is as modular and reusable as possible,
while also making sure it is easy to use and understand. Coupling
pieces of your code together can lead to some major headaches down
the road when you are trying to debug why something isn't working.
As for your question you can export the express from app.js or index and use it everywhere.
It is discouraged to use additional global variables as application already has 'export' and 'require' global variables. (exports/require are not keywords, but global variables.)
If you need to export the 'app' for other files, you can do something like below.
in index.js:
var express_app = module.exports = express();
now index.js can be required to bring app into any file.
in any.js file:
var express_app = require('./index');
New to Express. Want to implement an MVC pattern in Express and substitute routes folder with controller folder. I found this code, which actually works, but I don't really understand what it does:
var fs = require('file-system');
fs.readdirSync('controllers').forEach(function (file) {
if(file.substr(-3) == '.js') {
const route = require('./controllers/' + file);
route.controller(app);
}
})
The readdirSync reads the content of the folder 'controllers' and for each file it founds it does something that I don't understand:
if(file.substr(-3) == '.js') //checks if the end of the file is .js but why?
const route = require('./controllers/' + file); //don't understand this
route.controller(app); //don't understand this
Could you please help with this?
Thank you.
The example you follow comes from this blog entry by Tim Roberts. The example controller demonstrates what is it all about:
var mongoose = require('mongoose')
var Video = require('../models/user');
module.exports.controller = function(app) {
app.get('/signup', function(req, res) {
// any logic goes here
res.render('users/signup')
});
app.get('/login', function(req, res) {
// any logic goes here
res.render('users/login')
});
}
If you save this example controller in the controllers folder under whatever.js, all it does it exports a function, controller, that takes the express app as an argument and adds a couple of custom routes to the app.
Then, the main module scans all such files under the controllers folder and first uses the require function to load the module:
const route = require('./controllers/' + file);
After above line, the route contains a reference to the module that contains this controller function.
This
route.controller(app);
just calls the function exported from the module, passing the global app as an argument.
This way you can easily extend your app just by creating separate .js modules under controllers folder, that follow the same convention (export the controller function).
I made an web application where all my server side was in the same file.
To be clear, in my "app.js" i had :
Express routes
Socket.io events and more...
Differents objects reacting with pages events
I want to rework that project to do things properly and i started to do that. I have put my routes in different js files like login.js,subscribe.js, ... in a routes directory.
In my app.js I have added the line : require('./routes')(app);
I have a index.js file in /routes where i had placed my "Express router" which is managing all my routes.
index.js
module.exports = function (app) {
app.get('/signup', require('./subscribe').get);
app.post('/signup', require('./subscribe').post);
app.get('/', require('./login').get);
app.post('/', require('./login').post);
...
}
Is that the correct way to do with routes ?
The problem i meet is that i have an object named usersConnected {} that I fill with some properties when a member is logged in, etc...
This object is in my app.js file and I can't reach it from the other files like login.js...
app.js
// Express routing defined in ./routes/index.js
require('./routes')(app);
// Globals variables
var usersConnected = {};
var rooms = {};
...
login.js
An example of the usage of usersConnected
// If login and password matches with couple in database
usersConnected[login] = {
games: rows[0].games,
kills: rows[0].kills,
deaths: rows[0].deaths,
statut: "ACCUEIL",
adversaire: "NULL",
socket: "NULL",
wsId: "NULL",
room: "NULL",
lsid: funcs.computeRandomLsId(64)
};
And how i export my "route managing"
exports.get = (req, res) => {
if (!req.session.login)
...
}
I have some ideas but I think it's the bad way to proceed like exports my object where I need it or put my object alone in a .js file which will be imported, etc...
If you could give me some trails that would really help me.
Edit : I think my problem is the way i manage my sessions, because usersConnected contains all informations about all users connected... Maybe i should use express-session ?
I recommend you take a look at express-generator: http://expressjs.com/en/starter/generator.html . It provides a quite nice file structure for you to start. Even though it's quite opinionated, I found it very useful when I started and still do.
In the app.js file you will find something like this:
...
var routes = require('./routes/index');
app.use('/', routes);
This is a bit tedius if you have a lot of routes. Here you have a code snippet to do this dinamically. gist
Anyway, the point is that the express generator will help you evacuate your doubts and point you in the right direction.
I want to create web app with nodejs but with structure like this
- modules
| - module1
| - module1.js
| - module2
| - module2.js
- index.js
- settings.js
First, i never use nodejs from scratch
Second, i know you will suggest using any other framework, sorry guys here i want to understand how nodejs and may be other nodejs framework works.
Third, this is for educational purpose
in modules/module1/module1.js :
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
res.end('Hello World aw!')
honestly i dont know how to code it properly, what i really want is i wanna execute that code and response to browser Hello World aw! from index.js :
router.get('/', function (req, res) {
//in here i call modules/module1/module1.js, and execute the code
})
and how to do that properly? so it can run well
to load any script or module in nodejs you need to use require
like this
var module1 = require(__dirname + 'modules/module1/module1.js');
and then you can use module1 anywhere in your code
BTW for express you should create routes and then attach that routes to your app. See example below.
users.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
server.js
var express = require('express');
var app = express();
var users = require('./routes/users');
....
app.use('/users', users);
Every time with node when you need to have a module in a particular page you need to require this module.
example: you want to get the library express so at the top of your file who you want this library you do something like that.
var express = require('express');
Now you can use express in all the file. When this is a node library you just need to require the name.
this is the same thing with a file you create and you want inside a other one
var myfile = require('./../myfile');
with that you can use the word myfile inside all the file. But you need to figure out the path to this one.
A good links for read about this
I'm using a module called consign to include several different modules in a directory at once (instead of having a bunch of require statements). Within these modules, I've been setting the mount path for each endpoint at the top of the router file so as not to repeat it several times throughout the file. However, consign passes the same router to each of these (which should normally be fine) and the mount path is actually being overwritten via the use() method if the path is the same in any of the files. I'll try and show this the best way I can...
/routes/api.js
var express = require('express');
var router = express.Router();
var consign = require('consign');
// get all routes inside the api directory and attach them to the api router
// all of these routes should be behind authorization
consign({
cwd: 'routes'
})
.include('api')
.into(router);
module.exports = router;
/routes/api/player.js
module.exports = function (router) {
router.use('/player', router);
router.get('/getInfo', function (req, res, next) {
res.error = false;
res.data = {};
res.message = "Player getInfo API Call - IN DEVELOPMENT";
next();
});
};
/routes/api/profile.js
module.exports = function (router) {
router.use('/profile', router);
router.get('/getInfo', function (req, res, next) {
res.error = false;
res.data = {};
res.message = "Profile getInfo API Call - IN DEVELOPMENT";
next();
});
}
Consign is loading in the modules just fine, but the router.use() method seems to be overwriting the callbacks when the paths are the same (disregarding the base path that is). For instance, both "/player/getInfo" and "/profile/getInfo" work as a call, but are both responding with "/profile/getInfo" data.
BTW - in case you're wondering and in case it's pertinent, I have a small piece of middleware called "formatResponse" that will take the data and format all of the calls in the same way, which is why I have a "next()" instead responding from the function itself. The code for that is below as well.
/middleware/formateResponse.js
module.exports = function(req, res, next) {
res.json({
error: res.error,
data: res.data,
message: res.message
});
}
The way you're doing it right now, there's no scope. The fact that you mounted the router on '/profile' and then added a get statement to the '/getInfo' path doesn't really change the scope the way you think it does. They're both stored to match on '/getInfo', with the last one in winning (regardless of prefix. I bet navigating to http://your-server/getInfo will work too).
You either need to use a different router for each module (and then mount that one on the path root you want) or else be more explicit in the rest of the routes (e.g. call router.get('/profile/getInfo', ...).