Difference between app.get() or router.get() - ExpressJs - node.js

What is the difference between:
var express = new express();
var app = new express();
app.get("/", function() {
.....
})
And:
var express = new express();
var router= express.Router();
router.get("/", function() {
.....
})

app.get can be used to create routes for your application at the top level.
From the documentation about express.Router
Use the express.Router class 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”.
A router needs to be mounted to an app:
const router = express.Router();
router.get("/", (res, req) => res.end());
router.post("/", (res, req) => res.end());
app.use("/empty", router);
This allows you to more easily encapsulate the functionality of several routes into an app which will be namespaced under a particular route.

When express() is called in app.js, an app object is returned. Think of an app object as an Express application.
When express.Router() is called, a slightly different "mini app" is
returned. The idea behind the "mini app" is that different routes in
your app can become quite complicated, and you'd benefit from moving
that logic into a separate file.
Check this SO Thread for details.

Related

express.Router() vs express() in express

As mentioned in express routing guide and this answer, we can create "mini-app" and use it from the main app. However I saw a code where it uses app instead of router in the module
app.js
var express = require('express');
var userRoutes = require('./routes/user');
var app = express();
app.use('/user', userRoutes);
module.exports = app;
routes/user.js
var express = require('express');
var app = express(); // not express.Router() !!
app.get('/:name', function(req, res) {
var userName = req.params.name;
res.render('user.jade', {
userName: userName
});
});
module.exports = app;
I assumed the correct usage in routes/user.js should be
router = express.Router()
instead of
app = express()
but app = express() also works! what are the differences and why router = express.Router() is better?
When you are working with a server where there are many routes, it can be confusing to leave them in a Main file together. The let router = express.Router() option works differently than let app = express().
While the app returns an app object, router will return a small app fragment, similar to the app, where you will use logic to call them later on the Main.
The most important, about your question, is that a router, which is isolated, will not interfere with others in the application, being a single environment.
https://expressjs.com/en/api.html#router
A router object is an isolated instance of middleware and routes. You can think of it as a “mini-application,” capable only of performing middleware and routing functions. Every Express application has a built-in app router.
A router behaves like middleware itself, so you can use it as an argument to app.use() or as the argument to another router’s use() method.

Where is the domain mapped to app routers?

const express = require('express');
const router = express.Router();
router.get('/specialRoute', function (req, res, next) {
// route is now http://domain:3000/route/specialRoute
});
router.get('/', function (req, res, next) {
// route is now http://domain:3000
});
module.exports = router;
However, where is the 'domain' mapped to '/' ? In other words, where is the logic to route 'http://domain:3000' -> router.get('/',
An express.Router is not an express application (which is what is used for said binding).
Usually the mapping defaults to localhost because you assign a domain name to an IP and the DNS does the wiring.
If you look at Express's listen documentation on devdocs you'd see that you can pass a host as a second parameter : app.listen(80, "mywebsite");
If you want to map a router to the root ("the domain") you first need an express application:
const app = express();
Then, use the router:
app.use(router);
To make it even neater: Express apps themselves are instances of Router so if you replace router.get with app.get it will be functionally the same.
The reason you would want to create a new Router and export it would be to have multiple router modules and then require them from a main file like this:
const express = require("express");
const app = express();
app.use("/shop", require("./path-to-your-shop-router.js"));
Also, don't forget to make the server listen so you can visit it on your computer:
// Ports <1024 are usually restricted
app.listen(3000);

Node express routes as modules: where to put `require`s?

Node Express's Routing guide gives the following example for creating routes as modules:
/birds.js:
var express = require('express')
var router = express.Router()
// middleware that is specific to this router
router.use(function timeLog (req, res, next) {
console.log('Time: ', Date.now())
next()
})
// define the home page route
router.get('/', function (req, res) {
res.send('Birds home page')
})
// define the about route
router.get('/about', function (req, res) {
res.send('About birds')
})
module.exports = router
/app.js:
var birds = require('./birds')
// ...
app.use('/birds', birds)
I want to know why they put the first two lines of birds.js there instead of in app.js.
Firstly, app.js calls a method of app. How is app supposed to be defined within app.js? I take it they (oddly) neglected to include that necessary code for the sake of the tutorial.
Secondly, say I wanted a second route as a module, for dogs as well as birds, in a file called dogs.js. Could it look identical to birds.js WRT the first two lines? AFAIK that would result in two instances of express. (Or three if it's needed in app.js as well?!)
The example is not complete. The whole app setup is left out (i asume because it is explained further up in the docs anyway and replaced with // ...). In your app.js you need at least:
var express = require('express');
var app = express();
The first 2 lines in bird.js have nothing to do with the two (missing) lines in app.js. You need them to create a router.
And regarding your last question: Yes, you would create another router exactly like the bird router. A router is not an express app/instance and it's totally fine to have multiple of them in you app.

Express JS Router Middleware Abstraction

I have developed an API using Node.js + Express JS and i use token-based authentication.
I used two differents routers in this api, userRoute (/USER) and postRoute (/POST). The postRoute can be used within authentication but userRoute needs the token.
To solve that i use a router middleware for userRoute but it interferes with portRoute
This is the code:
...
var postRoute = express.Router();
var userRoute = express.Router();
// Route middleware to verify a token
userRoute.use(function(req, res, next) {
security.checkToken(req,res, next);
});
userRoute.route('/users')
.get(userCtrl.findAllUsers)
.post(userCtrl.addUser);
postRoute.route('/posts')
.get(userCtrl.findAllPosts)
.post(userCtrl.addPost);
app.use(userRoute);
app.use(postRoute);
...
If i try to access '/posts' the servers checks the token and does not let me in. I know if i change the order of app.use it works, but i dont understand why works in this way if i am using "Router Middleware".
Someone knows?
This happens because if the express router implementation, you will be able to understand it quite easily if you have a look at it. Here is the path: node_modules/express/lib/router/index.js. Every time that you call the Router(), like in your case
var postRoute = express.Router();
var userRoute = express.Router();
this function will be invoked:
var proto = module.exports = function(options) { ... }
and it is true that there is a different router instance that is being returned every time. The difference is in the way that the use is registering the middlewares. As you see the use it is registered against the proto.use
proto.use = function use(fn) { ... }
this means that the middleware that you register there they will be registered for every instance of the router that you define.

Overwrite the Express router

I wanted to create MVC based architecture on the express for that I want to overwrite the Express Router.
Consider following as an example:
// usual express router
var userRouter = require('express').Router();
userRouter.get("/",function(req, res, next){
//.....
});
userRouter.post("/",function(req, res, next){
//.....
});
app.use('/users', userRouter);
//routes.js
module.exports = function(app){
var userRouter = app.Router();
userRouter.get('/', {controller: 'User', action: 'show'});
userRouter.post('/', {controller: 'User', action: 'new'});
app.use('/users', userRouter);
};
So, do I have to implement router again like the express with my controller parsing functionality?
Rewriting already existing functionality is commonly accepted as bad practice. Express has the option to modify data via middleware services.
If neither the native router, nor the middleware functionality works for you, then maybe you should go and change the framework to Hapi.
I judge my own short experience, Hapi provides better accommodation for routing and server magic.

Resources