Version | Changes |
---|---|
v12.2.0 | Middleware is stable |
v12.0.9 | Enforce absolute URLs in Edge Runtime (PR) |
v12.0.0 | Middleware (Beta) added |
Middleware allows you to run code before a request is completed, then based on the incoming request, you can modify the response by rewriting, redirecting, adding headers, or setting cookies.
Middleware runs before cached content, so you can personalize static files and pages. Common examples of Middleware would be authentication, A/B testing, localized pages, bot protection, and more. Regarding localized pages, you can start with i18n routing and implement Middleware for more advanced use cases.
Note: If you were using Middleware prior to
12.2
, please see the upgrade guide.
To begin using Middleware, follow the steps below:
npm install next@latest
middleware.ts
(or .js
) file at the same level as your pages
directorymiddleware.ts
file:// middleware.ts import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' // This function can be marked `async` if using `await` inside export function middleware(request: NextRequest) { return NextResponse.redirect(new URL('/about-2', request.url)) } // See "Matching Paths" below to learn more export const config = { matcher: '/about/:path*', }
Note the
pageExtensions
config affects middleware as well, see related documentation here.
Middleware will be invoked for every route in your project. The following is the execution order:
headers
from next.config.js
redirects
from next.config.js
rewrites
, redirects
, etc.)beforeFiles
(rewrites
) from next.config.js
public/
, _next/static/
, Pages, etc.)afterFiles
(rewrites
) from next.config.js
/blog/[slug]
)fallback
(rewrites
) from next.config.js
There are two ways to define which paths Middleware will run on:
matcher
allows you to filter Middleware to run on specific paths.
export const config = { matcher: '/about/:path*', }
You can match a single path or multiple paths with an array syntax:
export const config = { matcher: ['/about/:path*', '/dashboard/:path*'], }
Note: The
matcher
values need to be constants so they can be statically analyzed at build-time. Dynamic values such as variables will be ignored.
// middleware.ts import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' export function middleware(request: NextRequest) { if (request.nextUrl.pathname.startsWith('/about')) { return NextResponse.rewrite(new URL('/about-2', request.url)) } if (request.nextUrl.pathname.startsWith('/dashboard')) { return NextResponse.rewrite(new URL('/dashboard/user', request.url)) } }
The NextResponse
API allows you to:
redirect
the incoming request to a different URLrewrite
the response by displaying a given URLTo produce a response from Middleware, you should rewrite
to a route (Page or Edge API Route) that produces a response.
The cookies
API extends Map and allows you to get
, set
, and delete
cookies. It also includes methods like entries and values.
// middleware.ts import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' export function middleware(request: NextRequest) { // Setting cookies on the response const response = NextResponse.next() response.cookies.set('vercel', 'fast') response.cookies.set('vercel', 'fast', { path: '/test' }) // Getting cookies from the request const cookie = request.cookies.get('vercel') console.log(cookie) // => 'fast' const allCookies = request.cookies.entries() console.log(allCookies) // => [{ key: 'vercel', value: 'fast' }] const { value, options } = response.cookies.getWithOptions('vercel') console.log(value) // => 'fast' console.log(options) // => { Path: '/test' } // Deleting cookies response.cookies.delete('vercel') response.cookies.clear() return response }