前面我们学习了路由处理器,本节来聊聊代理。在实际开发中,我们经常需要处理跨域请求、API 代理等问题,Next.js 提供了几种配置代理的方式。
代理概述
Next.js 提供三种配置方式:
- Rewrites(重写)- URL 重写,用户不可见
- Redirects(重定向)- URL 重定向,用户可见
- Middleware(中间件)- 动态代理逻辑
理解这三者的区别和使用场景很重要。
重写(Rewrites)
基本 Rewrite
重写允许你将一个路径映射到另一个路径,而不会改变用户看到的 URL:
// next.config.js module.exports={asyncrewrites(){return[{source:'/about', destination:'/about-us',},{source:'/blog/:slug', destination:'/posts/:slug',},]},}API 代理
最常见的用途是代理 API 请求,解决跨域问题:
// next.config.js module.exports={asyncrewrites(){return[{source:'/api/:path*', destination:'https://external-api.com/:path*',},]},}这样,所有/api/*的请求都会被代理到https://external-api.com/*。
多个后端服务
module.exports={asyncrewrites(){return[{source:'/api/users/:path*', destination:'https://user-service.com/:path*',},{source:'/api/posts/:path*', destination:'https://post-service.com/:path*',},]},}重定向(Redirects)
基本 Redirect
重定向会改变用户看到的 URL,并返回 307 或 308 状态码:
// next.config.js module.exports={asyncredirects(){return[{source:'/old-path', destination:'/new-path', permanent: false, // 临时重定向(307)},{source:'/legacy/:path*', destination:'/new/:path*', permanent: true, // 永久重定向(308)},]},}通配符重定向
module.exports={asyncredirects(){return[{source:'/blog/:slug', destination:'/articles/:slug', permanent: true,},{source:'/categories/:category/products/:product', destination:'/products/:product', permanent: true,},]},}带查询参数的重定向
module.exports={asyncredirects(){return[{source:'/old-page', destination:'/new-page?from=old', permanent: false,},]},}中间件(Middleware)
中间件提供了更灵活的代理方式,可以在请求被处理前执行逻辑。
基本中间件
// middleware.tsimport{NextResponse}from'next/server'importtype{NextRequest}from'next/server'exportfunctionmiddleware(request: NextRequest){// 重写请求if(request.nextUrl.pathname.startsWith('/api/external')){const url=request.nextUrl.clone()url.href='https://external-api.com'+ request.nextUrl.pathnamereturnNextResponse.rewrite(url)}returnNextResponse.next()}exportconst config={matcher:'/api/:path*',}动态代理
// middleware.tsimport{NextResponse}from'next/server'importtype{NextRequest}from'next/server'exportfunctionmiddleware(request: NextRequest){const authHeader=request.headers.get('authorization')// 检查认证if(!authHeader){returnNextResponse.redirect(new URL('/login', request.url))}// 代理请求到后端if(request.nextUrl.pathname.startsWith('/api')){const url=new URL(request.url)const backendUrl=`https://backend.com${url.pathname}${url.search}`const proxyRequest=new Request(backendUrl,{method: request.method, headers: request.headers, body: request.body,})returnfetch(proxyRequest)}returnNextResponse.next()}处理 CORS
// middleware.tsimport{NextResponse}from'next/server'importtype{NextRequest}from'next/server'exportfunctionmiddleware(request: NextRequest){// 处理 OPTIONS 请求if(request.method==='OPTIONS'){returnNextResponse.json({},{headers:{'Access-Control-Allow-Origin':'*','Access-Control-Allow-Methods':'GET, POST, PUT, DELETE, OPTIONS','Access-Control-Allow-Headers':'Content-Type, Authorization',},})}// 处理实际请求 const response=NextResponse.next()// 添加 CORS 头 response.headers.set('Access-Control-Allow-Origin','*')response.headers.set('Access-Control-Allow-Methods','GET, POST, PUT, DELETE')response.headers.set('Access-Control-Allow-Headers','Content-Type, Authorization')returnresponse}常见场景
代理第三方 API
// next.config.js module.exports={asyncrewrites(){return[{source:'/api/external/:path*', destination:'https://api.external.com/:path*',},]},}解决跨域问题
// next.config.js module.exports={asyncheaders(){return[{source:'/api/:path*', headers:[{key:'Access-Control-Allow-Origin', value:'*'},{key:'Access-Control-Allow-Methods', value:'GET, POST, PUT, DELETE, OPTIONS'},{key:'Access-Control-Allow-Headers', value:'Content-Type, Authorization'},],},]},}移除路径前缀
module.exports={asyncrewrites(){return[{source:'/api/v1/:path*', destination:'/api/:path*',},]},}实用建议
这里分享几个在配置代理时特别有用的技巧。
使用 Rewrites 处理 API 代理
实际开发中,我发现使用 Rewrites 是处理 API 代理最简单的方式:
// 推荐这样做 - 使用 Rewrites{source:'/api/:path*', destination:'https://backend.com/:path*',}// 虽然也可以自己实现代理逻辑,但没必要使用 Redirects 处理 URL 变更
这里有个小建议:处理 URL 变更时,记得选择合适的配置方式:
// 推荐这样做 - 永久变更使用 Redirects{source:'/old-path', destination:'/new-path', permanent: true,}// 临时变更或不希望用户看到 URL 变化,才用 Rewrites使用 Middleware 处理复杂逻辑
这个技巧特别有用——处理认证等复杂逻辑时,Middleware 是最佳选择:
// 推荐这样做 - 用 Middleware 处理认证等复杂逻辑exportfunctionmiddleware(request: NextRequest){if(!isAuthenticated(request)){returnNextResponse.redirect(new URL('/login', request.url))}returnNextResponse.next()}总结
本节我们学习了 Next.js 的代理配置,包括 Rewrites、Redirects 和 Middleware。合理使用这些配置能让你更好地处理跨域、API 代理等问题。
如果你对本节内容有任何疑问,欢迎在评论区提出来,我们一起学习讨论。
原文地址:https://blog.uuhb.cn/archives/next-js-16.html