How to Use Middleware for Rewrite in Next.js
In Next.js, use
middleware.ts to intercept requests and rewrite URLs by returning a NextResponse.rewrite() with the new path. This lets you change the request URL before it reaches your pages or API routes.Syntax
The middleware function runs on every request matching its matcher pattern. Use NextResponse.rewrite(url) to rewrite the request URL.
request: The incoming request object.NextResponse.rewrite(url): Returns a response that rewrites the URL tourl.matcher: Defines which paths the middleware applies to.
typescript
import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { // Rewrite the request URL return NextResponse.rewrite(new URL('/new-path', request.url)); } export const config = { matcher: '/old-path/:path*', };
Example
This example rewrites requests from /blog/:slug to /news/:slug dynamically using middleware.
typescript
import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { const { pathname } = request.nextUrl; if (pathname.startsWith('/blog/')) { const newPathname = pathname.replace('/blog/', '/news/'); return NextResponse.rewrite(new URL(newPathname, request.url)); } return NextResponse.next(); } export const config = { matcher: '/blog/:path*', };
Output
When you visit /blog/my-article, the URL is rewritten internally to /news/my-article and the content from /news/my-article is served.
Common Pitfalls
- Not setting the
matchercorrectly causes middleware to run on unwanted paths or not at all. - Forgetting to return
NextResponse.next()when no rewrite is needed can block requests. - Using absolute URLs incorrectly in
NextResponse.rewrite()can cause errors; always usenew URL(path, request.url).
typescript
/* Wrong: Missing matcher, rewrites all requests unintentionally */ import { NextResponse } from 'next/server'; export function middleware(request) { return NextResponse.rewrite('/new-path'); // Incorrect usage without URL object } /* Right: Use matcher and proper URL object */ import { NextResponse } from 'next/server'; export function middleware(request) { return NextResponse.rewrite(new URL('/new-path', request.url)); } export const config = { matcher: '/old-path/:path*' };
Quick Reference
| Feature | Description | Example |
|---|---|---|
| middleware function | Intercepts requests to rewrite or redirect | export function middleware(request) { ... } |
| NextResponse.rewrite() | Rewrites the request URL internally | return NextResponse.rewrite(new URL('/new-path', request.url)); |
| matcher config | Defines which paths middleware applies to | export const config = { matcher: '/old-path/:path*' }; |
| NextResponse.next() | Continues without changes if no rewrite | return NextResponse.next(); |
Key Takeaways
Use middleware with NextResponse.rewrite() to change request URLs dynamically in Next.js.
Always define a matcher to limit middleware to specific paths for better performance.
Return NextResponse.next() when no rewrite is needed to avoid blocking requests.
Use new URL(path, request.url) to create correct URLs for rewriting.
Middleware runs before rendering, so rewrites happen server-side and are transparent to users.