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.
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');
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');
});
This has been driving me crazy. I'm new to NodeJS. I love it so far but some things have been throwing me off. I was handed a very basic starting point to a node project and I'm unsure how to search google for this.
//myapp/server.js
var config = require('./config');
var app = express();
var api = require('./app/routes/api')(app, express); // <-- this?
app.use('/', api);
var server = app.listen(3000, function () {
console.log('\n============================');
console.log(' Server Running on Port 3000 ');
console.log('============================\n');
});
Then there's the api.js file that contains the routes.
//myapp/app/routes/api.js
var config = require('../../config');
var mysql = require('mysql');
module.exports = function(app, express) {
var api = express.Router();
api.all('/', function(req, res) {...});
api.all('/route-two', function(req, res) {...});
api.all('/another-route', function(req, res) {...});
return api;
}
Ideally I'd like to break up what's going on here into a more organized structure but, I want to understand what I'm doing exactly.
The main thing that is confusing me is this line
var api = require('./app/routes/api')(app, express);
I was unaware that you can have ()() next to each other without a . or something joining them. Can someone explain what is happening?
Also what is the point of (app, express)? It appears that app and express are getting passed to the api part of the application so it's scope can be reached? Am I way off?
If there is a cleaner approach to this I would love to get some insight. I appreciate any thoughts.
Thanks!
EDIT
To make sure I am understanding...
var api = require('require this file')(params available to this file);
Moving any requires from api.js to server.js then include those as parameters
var api = require('./app/routes/api')(config, app, express, mysql);
EDIT
After more helpful feedback from #AhmadAssaf #Gurbakhshish Singh and #guy mograbi
Modules I want to use in another file other than where they are require()ed should be passed in through the second set of ()
//.server.js
var config = require('./config');
var app = express();
var api = require('./app/routes/api')(config, app, express);
| | |
_____________/______/________/
/ / /
//.app/routes/api.js | | |
module.exports = function(config, app, express) {
var api = express.Router();
// code to handle routes
}
Could be wrong with this part but based on what I think I am understanding.
//.server.js
var config = require('./config');
var app = express();
var register = require('./app/routes/register')(config, app, express);
var login = require('./app/routes/login')(config, app, express);
| | |
_________________/______/________/
/ / /
//.app/routes/login.js | | |
module.exports = function(config, app, express) {...handle login...}
//.app/routes/register.js
module.exports = function(config, app, express) {...handle registration...}
etc. etc.
Hopefully my thinking is about right. I appreciate everyones help on this! :)
So basically you have to understand few thing
module.exports wraps a Javascript object and export it to be used as a pluggable piece of code around a node.js application
The wrapped javascript object can be a JSON object, Javascript variable, function, etc.
What you have up there in the api module is a function that takes two parameters. When you require that module you want to pass some constructors to that function and thats the use of the second () after the module name in the first ()
requiring express once in your program and passing the variable around is more or less a singleton pattern. What you can also do is pass the config object as well to the api module instead of requiring it again :)
var api = require('./app/routes/api')(app, express);
is Equivalent to:
var myFunc = require('./app/routes/api');
var api = myFunc(app, express);
and becauase of NodeJS's module loading procedure, the require('...') will be
plugged in by the piece of code that was exported at the path, it can be a object, function, simple variable, etc.
And as far as ()() goes the require() nodeJS will make it something like function(){}() in your case and this is valid javascript and rather very useful to write IIFE(Immediately-Invoked Function Expression) code
Quesiton 1
explain ()()
every language where a function can return a function you can have this syntax. imagine the following
function world(){ ... }
function hello(){
return world;
}
// ===>
hello()() // ==> would invoke hello and then world.
So when you see require('..')() then it means require('..') returns a function. You do this by writing the following:
module.exports = function(){}
and that function returns yet another function - in your case this means express.Router(); returns a function.
Question 2
is there a cleaner way to write this?
this is a discussion.. which is hard to answer. depends on your preferences. The only thing I can think of that might help you reach an answer is to use the express generator and see the structure the express team uses.. which is probably as clean as it gets.
express can generate a project for you with some code to start with. simply install it with npm install -g express and then run express - it will generate the project for you in the same directory where you ran it.
go over the generated project. I suggest follow the same pattern - this is what i do whenever i cick-off a project.
If something is still unclear or if you need me to elaborate, please comment so and I will edit the answer.
module.exports from api.js is a function, which takes two arguments: app, and express. Therefore, when you require it in server.js with require('./app/routes/api'), the value returned is that function. Since it's a function, you can just call it by putting parentheses after it, and passing in the arguments it expects (app and express), like so : require('./app/routes/api')(app, express).
I'm having trouble with this script
// App.js ( shrink )
var controller = require('./controller');
app.get('/', controller.index);
app.get('/home', controller.home);
// /controller/index.js
var meta = {
title: 'index',
description: ''
}
exports.index = function(req,res){
res.render('index', {
meta: meta
});
}
// /controller/home.js
var meta = {
title: 'glibet',
description: ''
}
exports.home = function(req,res){
res.render('home', {
meta: meta
});
}
Its returning me this Error: "Error: Route.get() requires callback functions but got a [object Undefined]"
Strangely enough it works just fine if i let app.get('/', controller.index); alone without the home route
I've tried a couple of corrections/alternatives in the code maintaining the system its way of invoking controller/files but it doesn't seem to fix the code, i will really appreciate any help.
PS: I'm trying to avoid setting a variable to each controller file, avoiding something like this code;
var homeController = require('./controllers/home');
var userController = require('./controllers/user');
app.get('/', homeController.index);
app.get('/login', userController.getLogin);
When you require ./controller, Node first looks for a file called controller. Failing that, it looks for a file called index.js inside the directory controller.
You are not requiring every file in a directory by using require() in this manner.
You could use a plugin such as require-dir for this purpose. However, my recommendation would be to require each file separately, so that you know exactly what you are making available to your page-- this prevents side effects where you accidentally leave a file in your routes directory that you didn't want required by your main application controller.
You are trying to require a directory of js files as an object. If you want to keep all of your controller files separate but have them represented in one object in your app, you could do something like this:
// /controller/controllers.js
var home = require('./home');
var index = require('./index');
module.exports = {
home: home.home,
index: index.index
}
By requiring './controller/controllers' you could keep all of your controller endpoints organized in different files while accessible in one object.
Is there a common convention for breaking up and modularizing the app.js file in an Express.js application? Or is it common to keep everything in a single file?
I have mine broken up as follows:
~/app
|~controllers
| |-monkey.js
| |-zoo.js
|~models
| |-monkey.js
| |-zoo.js
|~views
| |~zoos
| |-new.jade
| |-_form.jade
|~test
| |~controllers
| |-zoo.js
| |~models
| |-zoo.js
|-index.js
I use Exports to return what's relevant. For instance, in the models I do:
module.exports = mongoose.model('PhoneNumber', PhoneNumberSchema);
and then if I need to create a phone number, it's as simple as:
var PhoneNumber = require('../models/phoneNumber');
var phoneNumber = new PhoneNumber();
if I need to use the schema, then PhoneNumber.schema
(which assumes that we are working from the routes folder and need to go 1 level up and then down to models)
EDIT 4
The express wiki has a list of frameworks built on top of it.
Of those, I think Twitter's matador is structured pretty well. We actually used a very similar approach to how they load up parts of the app.
derby.js also looks extremely interesting. It's akin to meteor without all of the hype and actually gives credit where credit is due (notably, node and express).
EDIT 3
If you are a fan of CoffeeScript (I am not) and reeeeaaaaaally want the L&F of Rails, there is also Tower.js.
EDIT 2
If you are familiar with Rails and don't mind the bleed-over of some concepts there is Locomotive. It is a light-weight framework built on Express. It has a very similar structure as RoR and carries over some of the more rudimentary concepts (such as routing).
It's worth checking out even if you don't plan to use it.
EDIT 1
nodejs-express-mongoose-demo is very similar to how I have mine structured. Check it out.
Warning: referencing code I hacked together for node knockout, it kind of works but is far from elegant or polished.
To be more specific about splitting up app.js I have the following app.js file
var express = require('express'),
bootstrap = require('./init/bootstrap.js'),
app = module.exports = express.createServer();
bootstrap(app);
This basically means I place all my bootstrapping in a seperate file, then I bootstrap the server.
So what does bootstrap do?
var configure = require("./app-configure.js"),
less = require("./watch-less.js"),
everyauth = require("./config-everyauth.js"),
routes = require("./start-routes.js"),
tools = require("buffertools"),
nko = require("nko"),
sessionStore = new (require("express").session.MemoryStore)()
module.exports = function(app) {
everyauth(app);
configure(app, sessionStore);
less();
routes(app, sessionStore);
nko('/9Ehs3Dwu0bSByCS');
app.listen(process.env.PORT);
console.log("server listening on port xxxx");
};
Well it splits all the server initialization setup in nice chunks. Specifically
I have a chunk that sets up all my remote OAuth authentication using everyauth.
I have a chunk that configures my application (basically calling app.configure)
I have a little bit of code that punches less so it re-compiles any of my less into css at run time.
I have code that sets up all my routes
I call this small nko module
Finally I start the server by listening to a port.
Just for example let's look at the routing file
var fs = require("fs"),
parseCookie = require('connect').utils.parseCookie;
module.exports = function(app, sessionStore) {
var modelUrl = __dirname + "/../model/",
models = fs.readdirSync(modelUrl),
routeUrl = __dirname + "/../route/"
routes = fs.readdirSync(routeUrl);
Here I load all my models and routes as arrays of files.
Disclaimer: readdirSync is only ok when called before you start the http server (before .listen). Calling synchronious blocking calls at server start time just makes the code more readable (it's basically a hack)
var io = require("socket.io").listen(app);
io.set("authorization", function(data, accept) {
if (data.headers.cookie) {
data.cookie = parseCookie(data.headers.cookie);
data.sessionId = data.cookie['express.sid'];
sessionStore.get(data.sessionId, function(err, session) {
if (err) {
return accept(err.message, false);
} else if (!(session && session.auth)) {
return accept("not authorized", false)
}
data.session = session;
accept(null, true);
});
} else {
return accept('No cookie', false);
}
});
Here I punch socket.io to actually use authorization rather then letting any tom and jack to talk to my socket.io server
routes.forEach(function(file) {
var route = require(routeUrl + file),
model = require(modelUrl + file);
route(app, model, io);
});
};
Here I start my routes by passing the relevant model into each route object returned from the route file.
Basically the jist is you organize everything into nice little modules and then have some bootstrapping mechanism.
My other project (my blog) has an init file with a similar structure.
Disclaimer: the blog is broken and doesn't build, I'm working on it.
For maintainable routing organisation you can check out this article about the express-routescan node module and try it. This is the best solution for me.
I have my apps build on top of the express-generator tool. You can install it by running npm install express-generator -g and run it using express <APP_NAME>.
To give you a perspective, one of my smaller application's structure looked like this:
~/
|~bin
| |-www
|
|~config
| |-config.json
|
|~database
| |-database.js
|
|~middlewares
| |-authentication.js
| |-logger.js
|
|~models
| |-Bank.js
| |-User.js
|
|~routes
| |-index.js
| |-banks.js
| |-users.js
|
|~utilities
| |-fiat-converersion.js
|
|-app.js
|-package.json
|-package-lock.json
One cool thing I like about this structure I end up adopting for any express application I develop is the way the routes are organized. I did not like having to require each route files into the app.js and app.use() each route, especially as the file gets bigger. As such, I found it helpful to group and centralize all my app.use() on a ./routes/index.js file.
In the end, my app.js will look something like this:
...
const express = require('express');
const app = express();
...
require('./routes/index')(app);
and my ./routes/index.js will look something like this:
module.exports = (app) => {
app.use('/users', require('./users'));
app.use('/banks', require('./banks'));
};
I am able to simply require(./users) because I wrote the users route using express.Router() which allows me to "group" multiple routes and then export them at once, with the goal of making the application more modular.
This is an example of what you would fine on my ./routers/users.js route:
const router = require('express').Router();
router.post('/signup', async (req, res) => {
// Signup code here
});
module.exports = router;
Hopefully this helped answer your question! Best of luck!