Proxy 代理
2026年9月6日
从 Next.js 16 起,中间件文件和导出函数改叫 Proxy,能力没变,名字更贴近「请求到达页面前先拦一层」。升级可以用官方 codemod:
npx @next/codemod@canary middleware-to-proxy .
bash
它会把 middleware.ts / middleware() 改成 proxy.ts / proxy()。
基本写法
在项目源码根(有 src/ 就放 src/proxy.ts)导出 proxy:
import { NextRequest, NextResponse } from "next/server";
export async function proxy(request: NextRequest) {
console.log(request.nextUrl.pathname);
return NextResponse.next();
}
ts
不配 matcher 时,静态资源、HMR、页面、接口全都会进来,开发时日志会刷屏。先收窄范围。
matcher
export const config = {
matcher: "/api/:path*",
};
ts
多个路径、或排除 _next:
export const config = {
matcher: [
"/api/:path*",
"/home/:path*",
"/((?!_next/static|_next/image|.*\\.png$).*)",
],
};
ts
鉴权跳转
上一篇用 cookie 记登录。保护 /home 可以不再单独打检查接口:
import { NextRequest, NextResponse } from "next/server";
export async function proxy(request: NextRequest) {
const token = request.cookies.get("token");
const { pathname } = request.nextUrl;
if (pathname.startsWith("/home") && !token) {
return NextResponse.redirect(new URL("/", request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ["/home/:path*"],
};
ts
没 cookie 就 307 回首页;有就放行。
更细的匹配
matcher 可以写成对象:source + has(必须带上)+ missing(必须没有)。type 只能是 header、query、cookie。
import type { ProxyConfig } from "next/server";
export const config: ProxyConfig = {
matcher: [
{
source: "/home/:path*",
has: [
{ type: "header", key: "authorization" },
{ type: "query", key: "userId" },
],
missing: [{ type: "cookie", key: "guest" }],
},
],
};
ts
只有条件都满足时,proxy 才会跑。适合「带特定头才走这套逻辑」。
给接口加 CORS
import { NextRequest, NextResponse } from "next/server";
const cors = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
};
export async function proxy(request: NextRequest) {
if (request.method === "OPTIONS") {
return new NextResponse(null, { status: 204, headers: cors });
}
const res = NextResponse.next();
for (const [k, v] of Object.entries(cors)) {
res.headers.set(k, v);
}
return res;
}
export const config = {
matcher: "/api/:path*",
};
ts
生产环境把 * 换成明确的前端源。Proxy 还可以做简单限流、改请求头、把 /api 转到别的语言服务——先把 matcher 收紧,再往函数里加逻辑。
下一篇看样式:Tailwind、CSS Modules、Sass、全局 CSS。