390

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?

Paul D. Waite
  • 96,640
  • 56
  • 199
  • 270
nelson687
  • 4,353
  • 3
  • 17
  • 20
  • 46
    A `Router` doesn't `.listen()` for requests on its own. It's useful for separating your application into multiple modules -- creating a `Router` in each that the `app` can `require()` and `.use()` as middleware. – Jonathan Lonowski Feb 03 '15 at 17:33
  • 7
    As @JonathanLonowski hinted at, the `app.get(..)` syntax is just a shortcut to make working with `express.router` more convenient. If you're just starting out, don't worry about the specifics of the router. – soulprovidr Feb 03 '15 at 17:33
  • 1
    so you are saying that I should use for the moment only app.get()? still confused about when to use one or another – nelson687 Feb 03 '15 at 17:37
  • 15
    @nelson687 There isn't really a hard-set rule between them. If you feel the `app's` own routing methods, such as `app.get()`, are sufficient for your needs, use them. The `Router` is just there for convenience to help you organize the application across multiple modules. [From the guide](http://expressjs.com/guide/routing.html#express-router): "*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".*" – Jonathan Lonowski Feb 03 '15 at 18:02
  • good thanks, I reckon I'll realize when using express.Router will be useful for me. – nelson687 Feb 04 '15 at 15:22
  • 3
    Possible duplicate of [What is the difference between "express.Router" and routing using "app.get"?](http://stackoverflow.com/questions/23607058/what-is-the-difference-between-express-router-and-routing-using-app-get) – XIMRX Nov 16 '15 at 13:40
  • @XIMRX: The question above is referencing each other :D – Afrig Aminuddin Sep 04 '18 at 04:22
  • @nelson687 - If you are creating a lots of routers then it's better to use Router instead of app. Using router makes your application more cleaner easy to debug and more manageable. – kta Mar 08 '20 at 23:52

10 Answers10

474

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.

Nocturno
  • 9,579
  • 5
  • 31
  • 39
  • shouldn't you have to pass the app object on `app.use('/dogs', dogs)(app)` since you're defining routes there, additionally (and correct me if i'm wrong) if you do it this way the app object has all of the middle-ware previously placed on it and additional middle-ware will be added to the app object (assuming more middle-ware is in the dogs route). if you use `route.get('/dogs', route)` it only passes the middle-ware to the app object when interacting with the routes defined in that router and if the scope of app is outside of route it doesn't have access to that middle-ware. – Ravenous Oct 21 '15 at 14:43
  • 2
    You don't need to pass the app to the route, because the route is being passed to the app with `app.use('/dogs', show)`. This way the route is independent of the app, and can be reused in any Express app. Middleware placed anywhere before a route gets used by that route. If you place middleware above all routes in app.js, then all the routes will use that middleware. If you place middleware inside a route file (dogs.js), only that route will use it. If you place middleware after the GET route inside dogs.js, then only the POST route will use it (as long as it ends with a response). – Nocturno Oct 21 '15 at 17:14
  • Ahh my bad. I meant to put `app.get('/dogs'dogs,)(app)` since the question was about the get feature of app.get and route.get. you were showing how to separate the routes to make them manageable. But wouldn't my anacdote be correct if we're talking about `app.get` ? If I can get on a PC I'll edit my above comment. – Ravenous Oct 21 '15 at 19:29
  • 3
    My App still works when I use either express.Router() or express(), I couldn't understand the difference :( – Ajay Suwalka Jan 31 '16 at 17:51
  • 4
    @Ajay Suwalka I don't know how I can elaborate any more on what I've already said. The docs say "A router object is an isolated instance of middleware and routes". I also like @Jonathan Lonowski comment above, "A `Router` doesn't `.listen()` for requests on its own". That might be the main difference. – Nocturno Jan 31 '16 at 19:36
  • @Nocturno how do you suppose to use multiple handlers for a single route? For example, for `router.post('/')` how can I use multiple routes? And does it receive the `next` param too? – JohnnyQ Mar 26 '17 at 05:36
  • @Nocturno I'm using express with typescript. The above answer results in error "cannot redeclare block scoped variable express" & "cannot redeclare block scoped variable router." What should I do?? – Amirhosein Al Apr 08 '18 at 16:05
  • @AmirhoseinAl I think you have to use an import statement in TS. Try the following: `import * as express from "express";`. – Nocturno Apr 09 '18 at 01:47
  • Is `express.Router()` same as `require('router')`? – Shashwat Oct 31 '18 at 10:12
  • 1
    @Shashwat I don't think they're the same. Router() is defined and imported in the require('express') module. It looks like require('router') is importing a completely different module not associated with Express at all. – Nocturno Nov 01 '18 at 00:12
  • @Nocturno: Both `express()` and `express.Router()` return an object that has all the routing methods and can be mounted on another app object (that was returned by `express()`) using `app.use(path, miniapp)`. For some reason, however, a Router object doesn't have the `mountpath` property, for example. So I don't understand the advantage of using `express.Router()` over `express()`. I'm sure there is some advantage, but I can't understand from the documentation what it is. – Ron Inbar Sep 04 '20 at 09:08
35

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:

  1. Basic Routes: Home, About
  2. Route Middleware to log requests to the console
  3. Route with Parameters
  4. Route Middleware for Parameters to validate specific parameters
  5. 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.

Sam Dutton
  • 14,775
  • 6
  • 54
  • 64
Alireza Fattahi
  • 42,517
  • 14
  • 123
  • 173
15

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.

coolaj86
  • 74,004
  • 20
  • 105
  • 125
7
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.

TILAK
  • 97
  • 1
  • 3
7

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.

Mike
  • 14,010
  • 29
  • 101
  • 161
raj240
  • 646
  • 7
  • 17
3

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.

T.Soundarya
  • 33
  • 1
  • 5
3

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()

3

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
Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
1

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.

  • this doesn't mean that its useless, suppose you want to make a app which uses its own apis. There is literally no point in creating two different servers for an api. This can be done effecienty with routes. – random_hooman Feb 07 '22 at 11:04
-1

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.

taoliujun
  • 69
  • 4