Introduction
Middleware in Next.js allows you to run code before a request is completed, which can be useful for tasks like authentication, logging, or redirects. Next.js introduced middleware support starting from version 12, enabling you to create and use custom middleware for your application.
Understanding Next.js Middleware
Middleware functions run before a request is completed, allowing you to.
- Modify request and response objects
- Redirect requests
- Implement authentication and authorization
- Log information
Setting Up Middleware
Create a Middleware File
Create a _middleware.js file inside the pages directory or any specific subdirectory where you want the middleware to apply. Middleware in Next.js can be applied globally or to specific routes.
Example. Global Middleware.
// pages/_middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
const { pathname } = request.nextUrl;
// Redirect example
if (pathname === '/old-page') {
return NextResponse.redirect(new URL('/new-page', request.url));
}
// Add custom logic here
return NextResponse.next();
}
Example. Route-Specific Middleware.
Place the middleware file in the specific directory you want it to apply to.
// pages/api/_middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
// Middleware logic for API routes
return NextResponse.next();
}
Use Middleware for Authentication
Create middleware to protect certain pages by checking user authentication status.
// pages/_middleware.js
import { NextResponse } from 'next/server';
import { getToken } from 'next-auth/jwt';
export async function middleware(request) {
const token = await getToken({ req: request });
if (!token && request.nextUrl.pathname !== '/login') {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
Testing Middleware
Run your Development Server
Ensure middleware logic is correctly applied by running your development server.
npm run dev
Test Functionality
Test different routes and scenarios to verify that middleware behaves as expected.
- Check redirects
- Verify authentication checks
- Ensure middleware does not unintentionally block or modify requests
Advanced Middleware Techniques
Dynamic Middleware
You can create dynamic middleware to handle different environments or conditions.
// pages/_middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
const isDev = process.env.NODE_ENV === 'development';
if (isDev) {
console.log('Development mode');
}
return NextResponse.next();
}
Custom Response Headers
Add custom headers to responses.
// pages/_middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
const response = NextResponse.next();
response.headers.set('X-Custom-Header', 'MyHeaderValue');
return response;
}
Best Practices
- Keep It Simple: Avoid overly complex logic in middleware to maintain readability and performance.
- Limit Scope: Apply middleware only to necessary routes to avoid unintended side effects.
- Secure Middleware: Ensure middleware that handles authentication or sensitive data is secure and free from vulnerabilities.
Summary
Custom middleware in Next.js provides a powerful way to intercept and modify requests. By following this guide, you can create middleware to handle various tasks such as authentication, redirection, and response customization. Test your middleware thoroughly and adhere to best practices for a secure and efficient implementation.