如何在Next.js中通过middleware.ts文件使用多个中间件
在Next.js中无依赖实现多中间件的正确方式
Next.js官方并不支持你尝试的那种导出middleware数组的写法,要实现多个中间件逻辑,以下是三种无需外部包的可行方案:
方案1:单文件内按路径分支处理
这是最直接的方式,在主middleware函数中根据请求路径匹配对应逻辑:
import { NextResponse, NextRequest } from "next/server"; // 拆分独立的中间件逻辑函数 function profileMiddleware(request: NextRequest) { const userId = request.cookies.get("userId"); if (!userId) { return NextResponse.redirect(new URL("/auth/login", request.nextUrl.origin)); } return NextResponse.next(); } function authMiddleware(request: NextRequest) { const userId = request.cookies.get("userId"); if (userId) { return NextResponse.redirect(new URL("/", request.nextUrl.origin)); } return NextResponse.next(); } // 主middleware入口 export function middleware(request: NextRequest) { const path = request.nextUrl.pathname; // 匹配/profile开头的路径 if (path.startsWith("/profile")) { return profileMiddleware(request); } // 匹配/auth开头的路径 if (path.startsWith("/auth")) { return authMiddleware(request); } // 其他路径直接放行 return NextResponse.next(); } // 配置需要拦截的所有路径规则 export const config = { matcher: ["/profile/:path*", "/auth/:path*"], };
方案2:链式调用中间件(支持多逻辑串联)
如果需要对同一路径执行多个校验逻辑(比如先登录校验再权限校验),可以写一个简单的组合工具函数实现链式执行:
import { NextResponse, NextRequest } from "next/server"; // 定义中间件类型 type Middleware = (request: NextRequest) => NextResponse | Promise<NextResponse>; // 中间件组合工具:依次执行中间件,遇到非next响应则终止 function chain(middlewares: Middleware[]) { return async (request: NextRequest) => { for (const middleware of middlewares) { const response = await middleware(request); if (response !== NextResponse.next()) { return response; } } return NextResponse.next(); }; } // 示例:登录校验中间件 function authCheck(request: NextRequest) { const userId = request.cookies.get("userId"); if (!userId) { return NextResponse.redirect(new URL("/auth/login", request.nextUrl.origin)); } return NextResponse.next(); } // 示例:Profile权限校验中间件 function profilePermissionCheck(request: NextRequest) { const userId = request.cookies.get("userId")?.value; const targetProfileId = request.nextUrl.pathname.split("/")[2]; if (userId !== targetProfileId) { return NextResponse.redirect(new URL("/", request.nextUrl.origin)); } return NextResponse.next(); } // 主middleware入口 export function middleware(request: NextRequest) { const path = request.nextUrl.pathname; if (path.startsWith("/profile")) { // 链式执行多个中间件 return chain([authCheck, profilePermissionCheck])(request); } if (path.startsWith("/auth")) { const userId = request.cookies.get("userId"); if (userId) { return NextResponse.redirect(new URL("/", request.nextUrl.origin)); } return NextResponse.next(); } return NextResponse.next(); } export const config = { matcher: ["/profile/:path*", "/auth/:path*"], };
方案3:多文件拆分中间件(Next.js 13.1+)
如果追求模块化,Next.js支持创建多个独立的中间件文件,每个文件负责对应路径的逻辑:
比如项目结构:
your-project/ ├─ middleware/ │ ├─ profile.ts │ └─ auth.ts
middleware/profile.ts
import { NextResponse, NextRequest } from "next/server"; export function middleware(request: NextRequest) { const userId = request.cookies.get("userId"); if (!userId) { return NextResponse.redirect(new URL("/auth/login", request.nextUrl.origin)); } return NextResponse.next(); } export const config = { matcher: "/profile/:path*", };
middleware/auth.ts
import { NextResponse, NextRequest } from "next/server"; export function middleware(request: NextRequest) { const userId = request.cookies.get("userId"); if (userId) { return NextResponse.redirect(new URL("/", request.nextUrl.origin)); } return NextResponse.next(); } export const config = { matcher: "/auth/:path*", };
Next.js会自动加载所有匹配的中间件文件,各自独立生效。
内容的提问来源于stack exchange,提问作者l DraGSsine l
相关产品推荐
相关产品推荐

