Stop 05 · Express.js & Web FrameworksTopics · 12/14

Express Router

Part of the Backend Developer Roadmap

In short

One index.js with forty routes gets messy fast. express.Router lets you group related routes into their own files and plug each group in with one line.

Express's `Router` class lets you group related routes into their own modular, mountable mini-applications — essential for keeping a growing API organized.

The mascot points a customer towards one of several separate food court stalls.

Think of it like this

The college food court

The food court has separate stalls: dosa, chaat, juice. Each stall runs its own menu and staff, but they all share one entrance. Each Router is a stall with its own routes, and app.use mounts it at the entrance.

Watch it happen

An app built from routers

app
/api/users
/api/orders
GET /
GET /:id
requireAuth
GET /
POST /

1/5index.js creates the app and mounts two routers.

The big ideas

What you need to know

A mini app

A Router has its own routes and middleware. It behaves like a small Express app you can mount.

Paths are relative

Inside a router mounted at /api/users, router.get("/:id") answers /api/users/:id.

Group middleware

router.use(requireAuth) protects every route in that router, and only those.

One file per resource

routes/users.js, routes/orders.js. New teammates find code by guessing the file name.

See it in code

Walk through the code

js
1// routes/orders.js2import { Router } from "express";3import { requireAuth } from "../middleware/auth.js";4 5export const ordersRouter = Router();6ordersRouter.use(requireAuth);7 8ordersRouter.get("/", (req, res) => res.json({ userId: req.user.id, orders: [] }));9ordersRouter.post("/", (req, res) => res.status(201).json(req.body));10 11// index.js12import { ordersRouter } from "./routes/orders.js";13import { usersRouter } from "./routes/users.js";14app.use("/api/orders", ordersRouter);15app.use("/api/users", usersRouter);

1/4Create a router in its own file and export it.

To read a parent's route param inside a router, create it with Router({ mergeParams: true }).

Save yourself the pain

Common mistakes

Oops

Writing router.get("/api/orders/:id") inside a router mounted at /api/orders.

Do this instead

Inside the router, write just "/:id". The mount path is added for you.

Oops

Putting auth with app.use before all routers, so even public routes need login.

Do this instead

Attach auth to the routers or routes that need it, and leave health checks and login public.

Your mission

Split a big app

~30 min

Quick check

usersRouter has router.get("/:id/orders"), mounted with app.use("/api/users", usersRouter). Which URL matches?

Go deeper

  1. 1Split your routes into separate router files by resource (users, posts, orders).
  2. 2Mount each router under its own base path, e.g. `/api/users`.
  3. 3Apply router-level middleware (e.g. auth) that only affects routes in that router.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge