Explain Codes LogoExplain Codes Logo

Rest with Express.js nested router

javascript
nested-routers
express-router
mergeparams
Nikita BarsukovbyNikita Barsukov·Mar 5, 2025
TLDR

Nested routing with Express.js involves leveraging the express.Router(). This module lets you create manageable route handlers, and link them as needed. Below is a basic code to show this where parentRouter manages the main route and childRouter caters to the /child endpoint:

const express = require('express'); const app = express(); const parentRouter = express.Router(); const childRouter = express.Router(); childRouter.get('/', (req, res) => res.send('Hello from the child router!')); parentRouter.use('/child', childRouter); app.use('/', parentRouter); app.listen(3000);

Making sense of mergeParams in nested routers

In developing RESTful APIs, it's crucial to create a clear hierarchical structure, both for maintainability and readability. One feature of express.Router() that facilitates this is mergeParams: true. This option lets your nested router continually access parameters from its parent.

How to use mergeParams

Let's understand this mergeParams concept with user and items example:

const express = require('express'); // I'm the parent! const userRouter = express.Router(); // I'm the child, but I still respect my parent(userRouter)! const itemRouter = express.Router({ mergeParams: true }); // Now, itemRouter has access to user_id from the parent route itemRouter.get('/', (req, res) => { // I've got the power of the user_id! let userId = req.params.user_id; // Whoosh! Let's handle the part about fetching user's items res.send(`Items belonging to user ${userId}`); }); userRouter.use('/:user_id/items', itemRouter);

Building to scale

Routes structures are the backbone of your application, and as such, need to be able to scale as your application does. It's important to plan for a scalable route organization from the onset. A good practice is to use recursive routes loading through require on directories to auto-load and use all router modules from within the directory.

Modularity in structure

Keep your code modular and organized. Here's a pattern that might be helpful:

// user/index.js const express = require('express'); const router = express.Router(); const itemRouter = require('./item'); // Does anyone else have the feeling we are being used? router.use('/:user_id/items', itemRouter); module.exports = router; // app.js const userRouter = require('./routes/user'); // Developer might forget us, but app won't! app.use('/user', userRouter);

How to make your code clean and maintainable

It's key to keep your routes separated and logical for code clarity and maintainability. This separation of concerns is achieved with different routers handling related endpoints, such as a userRouter and itemRouter.

Retrieving and manipulating user data with express.Router()

The express.Router() feature is ideal for handling dynamic routes, such as retrieving and manipulating user data using user_id:

// user/item.js router.get('/:item_id', (req, res) => { // I am with my folks: user_id, item_id. Feeling close-knit here! const { user_id, item_id } = req.params; // fetch specific item for user res.send(`Picked up item ${item_id} for user ${user_id}`); });

Routing structures: drawing the line

For more complex API structures, it might be worth considering comprehensive solutions like actionhero or NestJS. These offer more advanced organization patterns and features.