Related
I'm starting with NodeJS and Express 4, and I'm a bit confused. I been reading the Express website, but can't see when to use a route handler or when to use express.Router.
As I could see, if I want to show a page or something when the user hits /show for example I should use:
var express = require('express')
var app = express()
app.get("/show", someFunction)
At the beginning, I thought this was old (for Express 3). Is that right or this is the way for Express 4 too?
If this is the way to do it in Express 4, what is express.Router used for?
I read almost the same example as above but using express.Router:
var express = require('express');
var router = express.Router();
router.get("/show", someFunction)
So, what's the difference between both examples?
Which one should I use if I just want to do a simple testing website?
app.js
var express = require('express'),
dogs = require('./routes/dogs'),
cats = require('./routes/cats'),
birds = require('./routes/birds');
var app = express();
app.use('/dogs', dogs);
app.use('/cats', cats);
app.use('/birds', birds);
app.listen(3000);
dogs.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('GET handler for /dogs route.');
});
router.post('/', function(req, res) {
res.send('POST handler for /dogs route.');
});
module.exports = router;
When var app = express() is called, an app object is returned. Think of this as the main app.
When var router = express.Router() is called, a slightly different mini app is returned. The idea behind the mini app is that each route in your app can become quite complicated, and you'd benefit from moving all that code into a separate file. Each file's router becomes a mini app, which has a very similar structure to the main app.
In the example above, the code for the /dogs route has been moved into its own file so it doesn't clutter up the main app. The code for /cats and /birds would be structured similarly in their own files. By separating this code into three mini apps, you can work on the logic for each one in isolation, and not worry about how it will affect the other two.
If you have code (middleware) that pertains to all three routes, you can put it in the main app, before the app.use(...) calls. If you have code (middleware) that pertains to just one of those routes, you can put it in the file for that route only.
Express 4.0 comes with the new Router. As mentioned on the site:
The express.Router class can be used to create modular mountable route
handlers. A Router instance is a complete middleware and routing
system; for this reason it is often referred to as a “mini-app”.
There is a good article at https://scotch.io/tutorials/learn-to-use-the-new-router-in-expressjs-4 which describes the differences and what can be done with routers.
To summarize
With routers you can modularize your code more easily. You can use routers as:
Basic Routes: Home, About
Route Middleware to log requests to the console
Route with Parameters
Route Middleware for Parameters to validate specific parameters
Validates a parameter passed to a certain route
Note:
The app.router object, which was removed in Express 4, has made a comeback in Express 5. In the new version, it is a just a reference to the base Express router, unlike in Express 3, where an app had to explicitly load it.
How they are different
Everyone, including the documentation, tends to refer back to how much they are the same, but not actually reference any differences. Well, they are, in fact, different.
var bigApp = express();
var miniApp = express.Router();
listen()
The most obviously difference is that the bigApp will give listen, which just a rather confusing way to do what would otherwise be simple and obvious the node http or https module:
var server = require('http').createServer(bigApp);
server.listen(8080, function () {
console.info(server.address());
});
I consider this an anti-pattern because it abstracts and obscures away something that wasn't complicated or difficult in the first place, and then makes it difficult for people to use websockets and other middleware that require the raw http server.
Internal State
The big difference, which is really important, is that all bigApps have separate internal state.
bigApp.enable('trust proxy');
bigApp.enabled('trust proxy');
// true
var bigApp2 = express();
bigApp2.enabled('trust proxy');
// false
bigApp.use('/bunnies', bigApp2);
// WRONG! '/bunnies' will NOT trust proxies
A miniApp passed to a bigApp, however, will be operated by the bigApp in such a way that its internal state and thisness will be preserved and those routes will behave accordingly.
bigApp.enable('trust proxy');
bigApp.enabled('trust proxy');
// true
var miniApp = express.Router();
bigApp.use('/bunnies', miniApp);
// CORRECT! All state and such are preserved
This can be a big deal because express does a lot of (sometimes trixy) things to the http.ServerRequest and httpServerResponse object - such as modifying (or hijacking) req.url and req.originalUrl and various other properties you've been using without realizing - and you probably don't want that duplicated and separated.
Smaller API
There is a smaller, more well-defined number of functions a Router can use:
.use(mount, fn)
.all(mount, fn)
.options(mount, fn)
.head(mount, fn)
.get(mount, fn)
.post(mount, fn)
.patch(mount, fn)
.put(mount, fn)
.delete(mount, fn)
.route(mount).XXXX
.param(name, cb).XXXX
There are a few other convenience methods as well, such as basic(), but you won't find set() or enable() or other methods that change the larger app state.
app.route('/book')
.get(function (req, res) {
res.send('Get a random book')
})
.post(function (req, res) {
res.send('Post a random book')
})
As in above example, we can add different HTTP request method under a route.
Let’s say your application is little complex. So what we do first is we divide the application into multiple modules so that changes in one module doesn't clutter the others and you can keep working on individual modules, but at the end of the day you need to integrate everything into one since you are building a single application. It is like we have one main application and few child applications whose parent is the main application.
So when we create the parent application we create one using
const express = require("express");
const parent = express();
And to this parent application we need to bring in the child applications. But since the child applications are not totally different applications (since they run in the same context - java term), express provides the way to do it by means on the Express's Router function and this is what we do in the each child module file and lets call one such child module as aboutme.
const express = require("express");
export const router = express.Router();
By export we are making this module available for other to consume and since we have modularized things we need to make the module files available to the parent application by means of node's require function just like any other third party modules and the parent file looks something like this:
const express = require("express");
const parent = express();
const child = require("./aboutme");
After we make this child module available to the parent, we need to tell the parent application when to use this child application. Lets say when a user hits the path aboutme we need the child application about me to handle the request and we do it by using the Express's use method:
parent.use("/aboutme", child);
and in one shot the parent file looks like this:
const express = require("express");
const parent = express();
const child = require("./aboutme");
parent.use("/aboutme", child);
Above all what the parent can do is it can start a server where as the child cannot. Hope this clarifies. For more information you can always look at the source code which takes some time but it gives you a lot of information.
using app.js to write routes means that they are accessible to all the users as app.js is loaded on application start. However, putting routes in express.router() mini apps protect and restrict their accessibility.
In a word , express.Routercan do more things when compares to app.get(),such as middleware, moreover, you can define one more router object with express.Router()
express.Router has many options:
enable case sensitivity: /show route to not be the same as /Show, this behavior is disabled by default
strict routing mode: /show/ route to not the same as /show, this behavior is also disabled by default
we can add specific middleware/s to specific routes
In one of the questions in the quiz this was asked: "express.Router() creates an object that behaves similar to the app object."
The correct answer is 'True'. I know that we can both create routers by using either of the two but is it safe to say that they are not the same in all cases? If my understanding is correct, the express() variable can do more things like start a server while the other one cannot.
In a complicated application, app is module, for example article and user. router is controller or action in module, for example article create and list.
E.g the url https://example.com/article/create parse article module and create router.
also app and router can be level-in-level.
// get dependencies
const express = require("express");
const http = require('http');
const app = express();
const server = http.createServer(app);
Why is there a need for app inside of http.createServer(app)? What is the difference between that and http.createServer()?
I've read the documentation but I still don't understand. Can anyone explain?
The reason why app is passed to http.createServer is related to Dependency Injection, a pattern for defining external dependencies.
http.createServer accepts external Classes that will be used internally to handle incoming messages and outgoing responses.
This allows you to write your own Classes to handle incoming/outgoing messages, without modifying http's internals yourself. In your case you are using Express's classes.
The method createServer expects an object that will define how the requests to the server will be handled. Check this. The app that you pass is in fact how you want each request handled. If you did not pass anything to it, it would just start a server and nothing would happen on each request received.
I'm starting with NodeJS and Express 4, and I'm a bit confused. I been reading the Express website, but can't see when to use a route handler or when to use express.Router.
As I could see, if I want to show a page or something when the user hits /show for example I should use:
var express = require('express')
var app = express()
app.get("/show", someFunction)
At the beginning, I thought this was old (for Express 3). Is that right or this is the way for Express 4 too?
If this is the way to do it in Express 4, what is express.Router used for?
I read almost the same example as above but using express.Router:
var express = require('express');
var router = express.Router();
router.get("/show", someFunction)
So, what's the difference between both examples?
Which one should I use if I just want to do a simple testing website?
app.js
var express = require('express'),
dogs = require('./routes/dogs'),
cats = require('./routes/cats'),
birds = require('./routes/birds');
var app = express();
app.use('/dogs', dogs);
app.use('/cats', cats);
app.use('/birds', birds);
app.listen(3000);
dogs.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('GET handler for /dogs route.');
});
router.post('/', function(req, res) {
res.send('POST handler for /dogs route.');
});
module.exports = router;
When var app = express() is called, an app object is returned. Think of this as the main app.
When var router = express.Router() is called, a slightly different mini app is returned. The idea behind the mini app is that each route in your app can become quite complicated, and you'd benefit from moving all that code into a separate file. Each file's router becomes a mini app, which has a very similar structure to the main app.
In the example above, the code for the /dogs route has been moved into its own file so it doesn't clutter up the main app. The code for /cats and /birds would be structured similarly in their own files. By separating this code into three mini apps, you can work on the logic for each one in isolation, and not worry about how it will affect the other two.
If you have code (middleware) that pertains to all three routes, you can put it in the main app, before the app.use(...) calls. If you have code (middleware) that pertains to just one of those routes, you can put it in the file for that route only.
Express 4.0 comes with the new Router. As mentioned on the site:
The express.Router class can be used to create modular mountable route
handlers. A Router instance is a complete middleware and routing
system; for this reason it is often referred to as a “mini-app”.
There is a good article at https://scotch.io/tutorials/learn-to-use-the-new-router-in-expressjs-4 which describes the differences and what can be done with routers.
To summarize
With routers you can modularize your code more easily. You can use routers as:
Basic Routes: Home, About
Route Middleware to log requests to the console
Route with Parameters
Route Middleware for Parameters to validate specific parameters
Validates a parameter passed to a certain route
Note:
The app.router object, which was removed in Express 4, has made a comeback in Express 5. In the new version, it is a just a reference to the base Express router, unlike in Express 3, where an app had to explicitly load it.
How they are different
Everyone, including the documentation, tends to refer back to how much they are the same, but not actually reference any differences. Well, they are, in fact, different.
var bigApp = express();
var miniApp = express.Router();
listen()
The most obviously difference is that the bigApp will give listen, which just a rather confusing way to do what would otherwise be simple and obvious the node http or https module:
var server = require('http').createServer(bigApp);
server.listen(8080, function () {
console.info(server.address());
});
I consider this an anti-pattern because it abstracts and obscures away something that wasn't complicated or difficult in the first place, and then makes it difficult for people to use websockets and other middleware that require the raw http server.
Internal State
The big difference, which is really important, is that all bigApps have separate internal state.
bigApp.enable('trust proxy');
bigApp.enabled('trust proxy');
// true
var bigApp2 = express();
bigApp2.enabled('trust proxy');
// false
bigApp.use('/bunnies', bigApp2);
// WRONG! '/bunnies' will NOT trust proxies
A miniApp passed to a bigApp, however, will be operated by the bigApp in such a way that its internal state and thisness will be preserved and those routes will behave accordingly.
bigApp.enable('trust proxy');
bigApp.enabled('trust proxy');
// true
var miniApp = express.Router();
bigApp.use('/bunnies', miniApp);
// CORRECT! All state and such are preserved
This can be a big deal because express does a lot of (sometimes trixy) things to the http.ServerRequest and httpServerResponse object - such as modifying (or hijacking) req.url and req.originalUrl and various other properties you've been using without realizing - and you probably don't want that duplicated and separated.
Smaller API
There is a smaller, more well-defined number of functions a Router can use:
.use(mount, fn)
.all(mount, fn)
.options(mount, fn)
.head(mount, fn)
.get(mount, fn)
.post(mount, fn)
.patch(mount, fn)
.put(mount, fn)
.delete(mount, fn)
.route(mount).XXXX
.param(name, cb).XXXX
There are a few other convenience methods as well, such as basic(), but you won't find set() or enable() or other methods that change the larger app state.
app.route('/book')
.get(function (req, res) {
res.send('Get a random book')
})
.post(function (req, res) {
res.send('Post a random book')
})
As in above example, we can add different HTTP request method under a route.
Let’s say your application is little complex. So what we do first is we divide the application into multiple modules so that changes in one module doesn't clutter the others and you can keep working on individual modules, but at the end of the day you need to integrate everything into one since you are building a single application. It is like we have one main application and few child applications whose parent is the main application.
So when we create the parent application we create one using
const express = require("express");
const parent = express();
And to this parent application we need to bring in the child applications. But since the child applications are not totally different applications (since they run in the same context - java term), express provides the way to do it by means on the Express's Router function and this is what we do in the each child module file and lets call one such child module as aboutme.
const express = require("express");
export const router = express.Router();
By export we are making this module available for other to consume and since we have modularized things we need to make the module files available to the parent application by means of node's require function just like any other third party modules and the parent file looks something like this:
const express = require("express");
const parent = express();
const child = require("./aboutme");
After we make this child module available to the parent, we need to tell the parent application when to use this child application. Lets say when a user hits the path aboutme we need the child application about me to handle the request and we do it by using the Express's use method:
parent.use("/aboutme", child);
and in one shot the parent file looks like this:
const express = require("express");
const parent = express();
const child = require("./aboutme");
parent.use("/aboutme", child);
Above all what the parent can do is it can start a server where as the child cannot. Hope this clarifies. For more information you can always look at the source code which takes some time but it gives you a lot of information.
using app.js to write routes means that they are accessible to all the users as app.js is loaded on application start. However, putting routes in express.router() mini apps protect and restrict their accessibility.
In a word , express.Routercan do more things when compares to app.get(),such as middleware, moreover, you can define one more router object with express.Router()
express.Router has many options:
enable case sensitivity: /show route to not be the same as /Show, this behavior is disabled by default
strict routing mode: /show/ route to not the same as /show, this behavior is also disabled by default
we can add specific middleware/s to specific routes
In one of the questions in the quiz this was asked: "express.Router() creates an object that behaves similar to the app object."
The correct answer is 'True'. I know that we can both create routers by using either of the two but is it safe to say that they are not the same in all cases? If my understanding is correct, the express() variable can do more things like start a server while the other one cannot.
In a complicated application, app is module, for example article and user. router is controller or action in module, for example article create and list.
E.g the url https://example.com/article/create parse article module and create router.
also app and router can be level-in-level.
I've been using the Node.js express module for some time now, without ever using the http module to listen to the port.
I'm wondering what are the benefits of using:
app = express();
app.listen(app.get('port'));
over
app = express();
var server = http.createServer(app).listen(app.get('port'));
My guess is that it's something to do with being able to set http settings such as maxSockets etc, but is there any other reason people do this?
From http://expressjs.com/api.html#app.listen:
The app.listen() method is simply a convenience method.
Here's the listen definition:
app.listen = function(){
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
Notice it passes its arguments to the server's listen call, so you can still sett http settings like maxSockets.
It also says, "if you wish to use HTTPS or provide both, use the technique above." The technique above it refers to is:
http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
So it seems one of the most common reasons not to use app.listen is if you want to have an https server.
I suppose you might need a reference to the return value of http.createServer for some reason, in which case you wouldn't want to use app.listen.
express is a layer on top of connect which is a layer on top of http.
HTTP Interface API http
The http API Comes from Node. Only provides the basic HTTP functionality out the box.
networking
request, response
events
listening
Middleware Layer connect
Connect is a middleware framework for node, which allows you to write modular HTTP apps. It provides a bunch of middleware out of the box
middleware
static middleware
bodyParser
cookieParser
compress
csrf
Web Application Framework express
Express provides an additional layer on top of connect, which allows you to do even more stuff, and actually build real applications with it. Most notably, it provides you with routing.
routing
template engine support
configuration
file upload abstraction
I have a bare-bone express application, exactly the one that is created with the express command.
I have installed socket.io and attached it to my server, like this:
var app = express(),
server = http.createServer(app),
io = io.listen(server);
server.listen(8000);
Now, I also have the routes files, which is called like this:
app.get('/', routes.index);
Inside this module I have the following function:
exports.index = function(req, res){
socket.emit('news', { message: "foo" });
};
This obviously leads to a 500 reference error, because the routes file is an exportable module, and obviously has no idea what the socket is, as it is located in the app.js file.
Is there a way I can access this socket object from this, or any other file? Please note that it is attached to the express generated app. Here is a link to said project: http://jsfiddle.net/E27yN
extra: what about getting/setting session data?
Thanks in advance.
If I'm reading this correctly, I had a very similar problem: Handling Node.js Async Returns with "require" (Node ORM)
The way I resolved it was by putting a function call to the require, and returning that function in my exports, then that was accessible via that local variable. In your case, I think it'd be something like this:
var routes = require("routes.js")(io);
console.log(routes.index()); // will log return of the function "index" in routes.js.
// in routes.js
module.exports = function(io) {
var exports = this;
exports.index = function(req,res,io) {
// now io.socket is available to routes
console.log(io);
}
return exports;
}
Now you can access whatever you've exported by using that variable. So getting and setting session data would be a matter of getting that info to/from the proper place and modifying it in your parent file (usually whatever you're launching with node, like app.js or what have you).
Hope this helps!
EDIT: After discussing this in the comments, I think the problem is you're trying to use express and socket.io on the same port.
The example they give in your link (http://socket.io/#how-to-use) actually shows that they are serving up index.html from app.get("/"). Index.html includes the socket.io script file () which is by default served up when you start your socket server.
That would look like this jsfiddle: http://jsfiddle.net/Lytpx/
Note that you serve up the index.html page through express, but your socket service actually serves up /socket.io.js which then makes connection calls to the listening socket service (note, you may want to change localhost in your io.connect call in index.html to whatever your server is).