Skip to Content
πŸŽ‰ Welcome to my notes πŸŽ‰
Express.jsAdvanced Routing with Express Router πŸ›£οΈ

Advanced Routing with Express Router πŸ›£οΈ

As your application grows, keeping all your routes in a single file (index.js or app.js) becomes unmanageable. Express Router is the solution to this problem. It’s a β€œmini-app” that allows you to group related routes into their own files, making your application more modular, organized, and easier to maintain.

Using express.Router for Modular Routes

The workflow involves creating a router in a separate file, defining routes on it, and then β€œmounting” that router in your main application file.

Create a Router File

First, create a new file for a specific part of your application, like products. Here, you define routes relative to the path where the router will be mounted. You create a router instance with express.Router() and define routes on it (e.g., router.get('/')). Finally, you export the router.

products.js
// routes/productRoutes.js const express = require("express"); // 1. Create a new router object const router = express.Router(); // A route for GET /products/ router.get("/", (req, res) => { res.send("Get a list of all products"); }); // A route for GET /products/123 router.get("/:productId", (req, res) => { res.send(`Get details for product with ID: ${req.params.productId}`); }); // 2. Export the router module.exports = router;

Mount the Router in Your Main App

In your main server file, you import the router file and tell your Express app to use it for a specific base path using app.use('/base-path', routerObject). Any request starting with that base path will then be handled by the corresponding router.

index.js
// app.js const express = require("express"); const app = express(); // 1. Import the router file const productRoutes = require("./routes/productRoutes"); // 2. Mount the router on the '/products' path // Any request starting with /products will be handled by productRoutes. app.use("/products", productRoutes); app.listen(3000, () => { console.log("Server is running on port 3000"); });

Now, a request to GET /products is handled by the router.get(’/’) handler, and a request to GET /products/123 is handled by the router.get(’/:productId’) handler.

Pre-loading Data with router.param()

router.param() is a special middleware that runs only when a specific route parameter is present in a route. It’s perfect for running pre-condition logic, like fetching a user or product from a database before the main route handler runs. This helps you avoid duplicating code across multiple route handlers that share the same parameter.

πŸ’» Code Example

Let’s add router.param() to our productRoutes.js file to simulate fetching a product.

products.js
// routes/productRoutes.js (updated) // ... (keep the existing router setup) // This middleware will run for any route that contains the ':productId' parameter router.param("productId", (req, res, next, id) => { console.log(`Fetching data for product ID: ${id}`); // In a real app, you would fetch the product from a database here. // For this example, we'll just attach some data to the request object. req.product = { id: id, name: "Sample Product" }; next(); // Pass control to the next handler }); // The route handler for GET /products/123 router.get("/:productId", (req, res) => { // The product data is already available on req.product! No need to fetch it here. res.send(`Details for ${req.product.name} (ID: ${req.product.id})`); }); // ... (export the router)

Complex Matching with Regular Expressions

For even more control, you can use regular expressions (RegExp) in your route paths. This is useful for enforcing a specific format for route parameters, ensuring that a route only matches if the parameter conforms to a certain pattern (e.g., consists only of digits).

πŸ’» Code Example

This route will only match if the :id parameter consists of exactly 5 digits.

index.js
// This route will match /users/12345 but NOT /users/abc or /users/123 app.get("/users/:id([0-9]{5})", (req, res) => { res.send(`User ID is valid: ${req.params.id}`); }); // A fallback route for invalid IDs app.get("/users/:id", (req, res) => { res.status(400).send(`Invalid User ID format provided.`); });

✨ Summary

  • express.Router is the standard way to organize your application’s routes into modular, manageable files.
  • You β€œmount” a router onto a specific path in your main app using app.use('/base-path', routerObject).
  • router.param() is a powerful tool for running middleware on specific route parameters, perfect for pre-loading data and reducing code duplication.
  • Regular Expressions can be used directly in route paths to create very specific matching rules for your URLs.
Last updated on