Advanced Routing: Dynamic Routes and Middleware in Next.js
In modern web development, static routes like /about or /contact are rarely enough. To build scalable applications like e-commerce platforms or social media feeds, you need to handle data-driven URLs and intercept requests before they even reach the page. This is where Dynamic Routes and Middleware come into play within the Next.js App Router architecture.
Understanding Dynamic Routes
Dynamic routes allow you to create pages where the URL segment is not known ahead of time. Instead of creating a folder for every single blog post or product, you define a placeholder segment that Next.js fills with actual data at runtime.
1. Basic Dynamic Segments
To create a dynamic segment, you wrap a folder name in square brackets: [id] or [slug]. For example, a file path of app/shop/[productId]/page.js will match routes like /shop/1, /shop/iphone, or /shop/blue-shirt.
// app/shop/[productId]/page.js
export default function ProductPage({ params }) {
return <h1>Displaying product: {params.productId}</h1>;
}
2. Catch-all Segments
Sometimes you need to capture multiple levels of a URL. By using an ellipsis inside brackets [...slug], you can match all subsequent segments. For example, app/docs/[...slug]/page.js matches /docs/setup, /docs/setup/installation, and so on.
- [...slug]: Matches one or more segments.
- [[...slug]]: Optional catch-all. Matches zero or more segments (including the root folder).
Introduction to Next.js Middleware
Middleware is a powerful feature that allows you to run code before a request is completed. It sits between the user's request and the server's response. This is the ideal place for authentication checks, redirects, and logging.
The Middleware Flowchart
[User Request]
|
v
[Middleware] -- (Check Auth / Redirect / Rewrite)
|
v
[Next.js Page / API Route]
|
v
[User Response]
Implementing Middleware
To use middleware, create a file named middleware.js (or .ts) in the root of your project. You can use the matcher configuration to define which routes the middleware should run on.
import { NextResponse } from 'next/server';
export function middleware(request) {
const token = request.cookies.get('auth-token');
// Redirect to login if no token is found on protected routes
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: '/dashboard/:path*',
};
Real-World Use Cases
- E-commerce Product Pages: Using
[slug]to fetch product details from a database based on the URL. - Authentication Guards: Using Middleware to protect the
/adminor/profilesections from unauthenticated users. - A/B Testing: Using Middleware to randomly redirect 50% of users to a new version of a landing page.
- Localization: Detecting user language via headers in Middleware and redirecting them to
/enor/esroutes.
Common Mistakes to Avoid
- Infinite Redirect Loops: Ensure your middleware doesn't redirect a user back to the same page it is currently protecting without a termination condition.
- Heavy Logic in Middleware: Middleware runs on the Edge Runtime. Avoid heavy computations or large libraries that might slow down every request.
- Forgetting the Matcher: If you don't define a matcher, your middleware will run on every single asset request, including images and fonts, which can impact performance.
Interview Notes for Developers
- Question: What is the difference between
[...slug]and[[...slug]]? - Answer:
[...slug]is a catch-all that requires at least one segment in the URL.[[...slug]]is an optional catch-all that can also match the base route without any extra segments. - Question: Where does Middleware execute?
- Answer: It executes in the Edge Runtime, which is a subset of Node.js APIs optimized for speed and low latency.
- Question: Can you access the database directly in Middleware?
- Answer: While possible, it is discouraged. Middleware should be lightweight. It is better to check for a session cookie or a JWT.
Summary
Advanced routing in Next.js transforms a simple collection of pages into a robust application. Dynamic Routes allow your application to handle thousands of unique data-driven pages with a single file template. Middleware provides a centralized layer to handle security and request logic before the page even renders. Mastering these two concepts is essential for building professional-grade React applications with Next.js.
In the next lesson, we will explore Data Fetching Strategies to see how we can populate these dynamic routes with real-time data from external APIs.