NextJS部署Vercel报Nested Middleware is not allowed错误
问题根因
该报错由Next.js版本迭代后Middleware规则变更导致:
- 旧版本Next.js支持在
pages/目录(含嵌套路由子目录)下放置_middleware.ts实现路由级中间件 - 新版本Next.js已废弃嵌套Middleware写法,强制要求所有中间件逻辑统一存放在项目根目录(与
pages/文件夹、package.json同级)的middleware.ts文件中,不再识别pages/目录下的任何中间件文件 - 将文件改名为
pages/middleware.ts触发本地报错,是因为next/server相关API仅允许在合法的Middleware文件中导入,pages目录下的文件会被识别为普通页面/路由文件,自然触发导入限制错误。
修复步骤
- 迁移中间件文件
将当前的pages/_middleware.ts直接移动到项目根目录,重命名为middleware.ts;如果你的项目使用src目录结构,则将文件放在src/middleware.ts路径下即可。 - 配置中间件生效范围
根目录的Middleware默认会匹配所有站点请求,你可以二选一控制生效范围:- 保留现有代码内的路径判断逻辑,即通过
if (req.nextUrl.pathname === "/")判断,仅在匹配目标路径时执行鉴权逻辑,其余路径直接放行 - 在文件末尾导出
config对象通过matcher指定匹配路径,性能优于代码内判断,示例如下:
如果需要匹配多组路径,// 仅匹配根路径 export const config = { matcher: "/", };matcher支持传入数组,例如matcher: ["/", "/user/:path*"]即可匹配根路径和user目录下所有子路径。 - 保留现有代码内的路径判断逻辑,即通过
- 修正代码参数问题
现有代码中middleware函数的第二个入参res: NextResponse是无效参数,新版本Middleware的入参仅保留请求对象,直接删除即可;同时补充未拦截请求的放行逻辑,避免请求卡住。修正后的完整可运行代码如下:import { getToken } from "next-auth/jwt"; import { NextRequest, NextResponse } from "next/server"; export async function middleware(req: NextRequest) { if (req.nextUrl.pathname === "/") { const session = await getToken({ req, secret: process.env.JWT_SECRET, secureCookie: process.env.NODE_ENV === "production", }); // 可根据业务需求扩展session校验逻辑,比如角色判断、权限校验等 if (!session) { const url = req.nextUrl.clone(); url.pathname = "/login"; return NextResponse.redirect(url); } } // 不符合拦截条件的请求直接放行 return NextResponse.next(); } // 可选:通过matcher配置生效路径,替代代码内路径判断 export const config = { matcher: "/", }; - 本地验证后部署
修改完成后删除本地.next缓存文件夹,重新执行构建命令验证无报错后,再将代码推送到Vercel即可正常部署,不会再触发NestedMiddlewareError。
注意事项
- 根目录的Middleware文件名不要加下划线前缀,必须命名为
middleware.ts/middleware.js - 如果之前存在多个嵌套路径下的
_middleware文件,需要将所有逻辑合并到这一个根目录Middleware文件中,通过路径判断或matcher配置分别处理不同路由的逻辑 - 不要将Middleware文件放在
pages/或app/目录内,否则依然会触发构建错误
内容的提问来源于stack exchange,提问作者Floky99
相关产品推荐
相关产品推荐

