The Router Class

Sub-Apps — Routes That Compose

The Router Class

Router lets you build self-contained route modules and mount them under a path prefix.

4 min read Level 1/5 #express#router#routing
What you'll learn
  • Create a Router
  • Mount under a prefix
  • Know the differences from `app`

express.Router() is a mini app you can compose. Same methods as appget, post, use, param — but it doesn’t bind to a port. You mount it under a URL prefix.

A Router

// users.js
import { Router } from "express";

const router = Router();

router.get("/",        listUsers);
router.post("/",       createUser);
router.get("/:id",     getUser);
router.delete("/:id",  deleteUser);

export default router;

Mounting It

// app.js
import express from "express";
import users from "./users.js";

const app = express();
app.use("/api/users", users);

Inside the router, paths are relative to the mount point:

  • router.get("/")GET /api/users
  • router.get("/:id")GET /api/users/:id

Per-Router Middleware

const router = Router();

router.use(requireAuth);           // applies to every route in router
router.use(express.json());

router.get("/", listUsers);

This middleware only runs for requests that hit this router. Great for “auth-required” route groups.

Routers Within Routers

const apiRouter = Router();
const usersRouter = Router();

usersRouter.get("/", listUsers);
apiRouter.use("/users", usersRouter);

app.use("/api/v1", apiRouter);
// → /api/v1/users

Compose as deep as you want. Each level can have its own middleware.

Router vs App

appRouter
Can .listen()yesno
Has app.set() settingsyesinherits from parent app
req.app availableyesyes (points to parent app)
Useful in testsyesyes (mount in a test app)

In practice you write almost everything as routers, and the root app.js is just glue.

mergeParams

If a parent router has :userId, an inner router can’t see it unless you opt in:

const userPosts = Router({ mergeParams: true });

userPosts.get("/", (req, res) => {
  console.log(req.params.userId);   // available
});

apiRouter.use("/users/:userId/posts", userPosts);

Without mergeParams: true, req.params only shows params captured inside the inner router.

Per-Resource Route Files →