Next middleware
参考文章:
https://www.ctnicholas.dev/articles/how-to-use-nextjs-middleware
文章内容多来自英文官网
介绍
中间件允许你在请求完成之前运行代码,然后根据传入的请求,你可以通过重写、重定向、修改请求或响应头,或直接响应来修改响应。
中间件在缓存内容之前运行,所以你可以对静态文件和页面进行个性化处理。中间件的常见例子是认证、A/B测试、本地化页面、僵尸保护等。关于本地化页面,你可以从
i18n
路由开始,为更高级的用例实施中间件。
使用中间间
-
创建
middleware.ts
(或者.js
)在src
的目录下(与页面文件同级别) -
导出
middleware
函数// 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*', }
匹配路径(Matching Paths)
中间件将为你的项目中的每一个路由被调用。以下是执行顺序:
headers
fromnext.config.js
redirects
fromnext.config.js
- Middleware (
rewrites
,redirects
, etc.) beforeFiles
(rewrites
) fromnext.config.js
- Filesystem routes (
public/
,_next/static/
, Pages, etc.) afterFiles
(rewrites
) fromnext.config.js
- Dynamic Routes (
/blog/[slug]
) fallback
(rewrites
) fromnext.config.js
###匹配器
匹配器可筛选出特定的路径允许中间件执行
export const config = {
matcher: '/about/:path*',
}
// 匹配多种情况路由
export const config = {
matcher: ['/about/:path*', '/dashboard/:path*'],
}
// 正则表达式匹配
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next/static (static files)
* - favicon.ico (favicon file)
*/
'/((?!api|_next/static|favicon.ico).*)',
],
}
匹配器的配置:
- 必须以
/
开头 /about/:path
可以匹配到/about/a
或者/about/b
,但是不能匹配到/about/a/b
- 在命名的参数上可以有修饰语(以:开头),
/about/:path*
可以匹配到/about/a/b
,因为*
是0次或者多次;?
是0次或者1次;+
是一次或者多次 - 可以使用括号内的正则表达式。
/about/(.*)
与/about/:path*
相同。
NextResponse
NextResponse
API可以实现以下功能:
- 重定向到一个不同的路由
- 重写一个给定路由
- 为路由API、
getServerSideProps
SSR渲染、重写 设置请求头(set request header) - 设置返回的
cookies
- 设置返回头(response header)
使用cookies
-
对于传入的请求,cookies有以下方法:
get
、getAll
、set
和delete
cookies。你可以用has
检查一个cookie是否存在,或者用clear
删除所有cookie。 -
对于发出的响应,cookies有以下方法:
get
、getAll
、set
和delete
。
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Assume(假设) a "Cookie:nextjs=fast" header to be present on the incoming request
// Getting cookies from the request using the `RequestCookies` API
const cookie = request.cookies.get('nextjs')?.value
console.log(cookie) // => 'fast'
const allCookies = request.cookies.getAll()
console.log(allCookies) // => [{ name: 'nextjs', value: 'fast' }]
request.cookies.has('nextjs') // => true
request.cookies.delete('nextjs')
request.cookies.has('nextjs') // => false
// Setting cookies on the response using the `ResponseCookies` API
const response = NextResponse.next()
response.cookies.set('vercel', 'fast')
response.cookies.set({
name: 'vercel',
value: 'fast',
path: '/test',
})
const cookie = response.cookies.get('vercel')
console.log(cookie) // => { name: 'vercel', value: 'fast', Path: '/test' }
// The outgoing response will have a `Set-Cookie:vercel=fast;path=/test` header.
return response
}
设置headers
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Clone the request headers and set a new header `x-hello-from-middleware1`
const requestHeaders = new Headers(request.headers)
requestHeaders.set('x-hello-from-middleware1', 'hello')
// You can also set request headers in NextResponse.rewrite
const response = NextResponse.next({
request: {
// New request headers
headers: requestHeaders,
},
})
// Set a new response header `x-hello-from-middleware2`
response.headers.set('x-hello-from-middleware2', 'hello')
return response
}
Note: 避免
headers
设置过大导致的431 Request Header Fields Too Large error depending on your backend web server configuration.