express.Router() vs express() in express - node.js

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.

Related

Express middleware on folder mounted app

I have an Express.js application running on https://mydomain.tld/folder. It sets up the route middlewares with
app.use('/path', middleware)
but only the one for the '/' path is working properly. I'm guessing this is because Express is looking for requests on https://mydomain.tld/path instead of on https://mydomain.tld/folder/path.
How can I get Express to process the requests for https://mydomain.tld/folder/path (preferably without having to hard code the path)?
Using a router:
// myRouter.js
var express = require('express')
var router = express.Router()
router.get('/path', middleware)
// other routes...
module.exports = router
Now you can use your router with the relative path you want:
var myRouter = require('./myRouter')
app.use('/folder', myRouter)

Prefix all requests in JSON Server with middleware

I'm using the JSON Server package (json-server) from https://github.com/typicode/json-server. I'd like to make the server prefix all requests with /api/v2. The documentation even gives an example how to do this with the following:
server.use('/api', router)
However I don't want to setup my own server instance but extend the default when running json-server.
Can I somehow use the above statement in a middleware?
Since the router that json-server returns to you is an Express router.
First define all of your /v1, /v2, etc in its own routes file as show below:
// api-routes.js
const express = require('express')
const jsonServer = require('json-server')
const router = express.Router()
const server = jsonServer.create()
const middlewares = jsonServer.defaults()
const v1Router = jsonServer.router('db-v1.json')
const v2Router = jsonServer.router('db-v2.json')
router.use('/v1', v1Router)
router.use('/v2', v2Router)
module.exports = router
Then mount your API router onto /api like so:
const express = require('express')
const apiRoutes = require('./api-routes')
const app = express()
app.use('/api', apiRoutes)
// ...
Should now have /api/v1 and /api/v2. Untested code above, but should give an idea what you need to do.

globalize my node variable express and route

Hello guys so i have this two variables i am requiring them for every route i have so i want to globalize them and just add them to the app.js but when i do that it didn't work.
var express = require('express');
var router = express.Router();
i tried to addd them in to my separate file config.js and then i require it in my route and assign it to variable and use it but it is not working.
my config file look like this
/**
* Module dependencies.
*/
var express = require('express'),
favicon = require('serve-favicon'),
logger = require('morgan'),
bodyParser = require('body-parser'),
methodOverride = require('method-override'),
errorHandler = require('errorhandler'),
path = require('path');
module.exports = function() {
var app = express();
var router = app.Router();
return app;
}();
i get this error all the time :
throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.');
TLDR: Your router variable is an instance of Router, and should to be initialized inside each of your route files. I can appreciate trying to be as DRY as possible, but doing it this way will not work the way you expect it to. You can save a bit of typing by writing it this way:
var router = require('express').Router();
The longer explanation is that use multiple routes, you need a router for each route. This is to help break up the whole path associated with a request (i.e. /bar/foo/baz) into more manageable chunks.
Let's say your path can start with either /cats or /dogs. In the file where you declare all your middleware, you could write:
var catRoute = require(./routes/cats)
var dogRoute = require(./routes/dogs)
app.use('/cats', catRoute)
app.use('/dogs', dogRoute)
Then, inside cats.js:
var router = require('express').Router();
router.get('/whiskers', (req, res) => {
res.send('Cat whiskers!')
}
module.exports = router;
What this does is tell the app if it gets a path starting with /cats, use the cats route, which is just another piece of middleware. Within the route itself, we don't have to specify /cats/whiskers, only /whiskers because app is only passing down the part of the path after /cats to the cats.
You can nest as many routers as you want. Check out this article for a good example of how to do that.
Hypothetically, you could use only one router

How to efficiently separate routing code

Dumb/Newb question...
I am learning/working on an API in Node / Express4 and I would like to break my routes out into another module. I have it working with the following code, but it seems awkward to me to keep re-using the require('express') statement... Is there a way to move more of the code from the routes.js file into server.js and still keep my .get and .post statements in the routes module? Thanks in advance!
server.js:
'use strict';
var express = require('express');
var routes = require('./routes');
var app = express();
app.use('/api', routes);
app.listen(3000, function() {
console.log('Listening);
});
routes.js
var express = require('express'); // how do I get rid of this line?
var router = express.Router(); // can I move this to server.js?
var apiRoute = router.route('');
apiRoute.get(function (req, res) {
res.send('api GET request received');
});
module.exports = router;
Your on the right track. Its actually cool to reuse the var express = require('express'); statement each time you need it. Importing, ( requiring ), modules is a cornerstone of modular development and allows you to maintain a separation of concerns with in the files of your project.
As far as modularly adding routes is concerned: The issue is that routes.js is misleading.
In order to modularly separate out your routes you should use several modules named <yourResource>.js. Those modules would contain all of the routing code as well as any other configuration or necessary functions. Then you would attach them in app.js with:
var apiRoute = router.route('/api');
apiRoute.use('/<yourResource', yourResourceRouter);
For example, if you had a resource bikes:
In app.js or even a module api.js:
var apiRoute = router.route('/api')
, bikeRoutes = require('./bikes');
apiRoute.use('/bikes', bikeRoutes);
Then in bike.js:
var express = require('express');
var router = express.Router();
var bikeRoutes = router.route('/');
bikeRoutes.get(function (req, res) {
res.send('api GET request received');
});
module.exports = bikeRoutes;
From there its easy to see that you can build many different resources and continually nest them.

Call twice the app variable in an express application

I have a file where I call all the require modules called 'app.js'
var express = require('express');
...
var app = express();
...
var routes = require('ruotes/index.js)
use('/', routes);
module.exports = app;
I call the index.js where I have all the routes
routes/index.js
var express = require('express');
var app = express();
/* import controllers */
var indexController = require('../controllers/index');
app.route('/')
.get(indexController.index);
module.exports = app;
The problem is I have two variables called app and I call twice express(). Does it exist a more elegant way to handle this situation? Maybe I could call the variable in router file in another way?
You are currently using a technique that is known as submounting.
If you want to avoid creating different instances of Express, you will have to pass your unique instance of Express as a parameter to your router, meaning that your index.js needs to export a function that accepts your app as a parameter.
Something like :
//=== routes/index.js
/* import controllers */
var indexController = require('../controllers/index');
module.exports = function(app){
app.route('/').get(indexController.index);
};
Doing so will allow you to keep the same instance of Express in your entire Web App.
Since you exported a function in index.js, you need to call it in app.js.
var express = require('express');
...
var app = express();
...
var routes = require('routes/index.js)(app)
module.exports = app;
You can use the same technique for routes, modules, models etc...
This technique will allow you to avoid re-requiring modules, and instantiating them, but you will need to write extra-bits to make sure your variables are passed from one side of your app to the other. Because of this, some prefer using the submounting technique, and requiring modules only where they are needed.

Resources