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
Related
I have 2 routes:
/api/system/list - list my systems
/api/system/:systemId/books/list - list books of current system
And different file for each API:
systemAPI.js:
const list = router.get('/list', Validate(Validation.list), listHandler)
return {
routes: [list]
}
bookAPI.js:
const list = router.get('/list', Validate(Validation.list), listHandler)
return {
routes: [list]
}
Finally, use the above routes:
express.use('/api/system', systemAPI.routes)
express.use('/api/system/:systemId/book', bookAPI.routes)
The problem is, when I'm entering list-books API (/api/system/:systemId/books/list), its actually calling the list-systems API (/api/system/list)
Update: Solved!
I had 2 main problems:
routes order (in app.use(..))
use different instance of Express.Router() on each API
Refer the answer below for more information.
Try reversing the order of the routes and this will probably solve your problem:
express.use('/api/system/:systemId/book', bookAPI.routes);
express.use('/api/system', systemAPI.routes);
The reason is that express evaluates routes 'greedily' and it will even resolve to partial matches. So, it is important to keep the more specific routes first before the more general ones.
Also, I think you are using the express router wrong according to the documentation the systemAPI:
const express = require('express');
const router = express.Router();
router.get('/list', Validate(Validation.list), listHandler)
module.exports = router;
The bookAPI route:
const express = require('express');
const router = express.Router();
router.get('/list', Validate(Validation.list), listHandler)
module.exports = router;
Finally import the routers and use them:
const express = require('express');
const bookRouter = require('./bookAPI'); //set the file paths based on your file structure
const systemRouter = require('./systemAPI');
const app = express();
app.use('/api/system/:systemId/book', bookRouter);
app.use('/api/system', systemRouter);
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.
In the nodejs+express application can we have different routes files and include them into a single file. Like as below.
in hotel.routes.js I have few routes like
const express = require("express");
const hotelsCtrl = require("../controllers/hotels.controller");
const router = express.Router();
router
.route("/")
.get(hotelsCtrl.getAllHotels);
module.exports = router;
In the review.routes.js I have few routes like
const express = require("express");
const reviewsCtrl = require("../controllers/reviews.controller");
const router = express.Router();
router
.route("/")
.get(reviewsCtrl.getAllreviews);
module.exports = router;
Now I wanted to include both hotel.routes.js and review.routes.js in the index file and when the route is "/hotel" it should go to hotel.routes.js and when the route is "/review" it should go to review.routes.js
can someone please help in fixing this.
Thanks in advance.
You can do this:
app.use('/hotel', require('./hotel.routes.js'));
app.use('/review', require('./review.routes.js'));
This puts the hotel.routes.js exported router on /hotel and the review.routes.js exported router on /review.
It seems like you've a bit over complicated things by using three files in order to set up a single /hotel route.
You could also just do:
const hotelsController = require("../controllers/hotels.controller");
app.get('/hotel', hotelsController.getAllHotels);
There's really no need for the separate hotel.routes.js file.
Of, alternatively you could put the /hotel in the hotel.routes.js file like this:
const hotelsCtrl = require("../controllers/hotels.controller");
const router = require("express").Router();
router.get('/hotel', hotelsCtrl.getAllHotels);
module.exports = router;
And, then all you have to do in index.js is this:
app.use(require('./hotel.routes.js'));
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.
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.