NextJS 12.2 middleware重定向受保护路由空白页报错
问题原因
Next.js 12.2+ 版本中,根目录下的middleware.js默认会拦截站点下所有请求,包括框架生成的静态资源(/_next/路径下的JS、CSS、图片资源)、公共静态文件、favicon等。
你当前的代码没有对这类静态资源做放行处理,未登录状态下浏览器请求react-refresh.js、webpack.js这类脚本资源时,也会被middleware重定向到/login路由,返回的是登录页的HTML内容。浏览器把HTML文档当作JS脚本解析,就会抛出Uncaught SyntaxError: Unexpected token '<'错误,所有脚本加载失败导致页面空白。
你之前给matcher枚举具体路由后正常,本质是因为缩小了middleware的匹配范围,没有命中静态资源路径而已。
解决方案
不需要逐一枚举所有受保护路由,只需要让middleware跳过所有不需要鉴权的静态资源、系统路径即可,两种实现方式选一种就行:
方式1:通过matcher配置排除静态路径(推荐)
Next.js的matcher支持正则负向匹配,直接配置排除所有静态资源相关路径,其余所有业务路由都会自动经过middleware处理:
// src/middleware.js import { NextResponse } from 'next/server'; export function middleware(req) { const userSession = req.headers.get('cookie'); const reqUrl = req.nextUrl.pathname; if (userSession?.includes('userToken')) { if (reqUrl.startsWith('/login')) { return NextResponse.redirect(new URL('/', req.url)); } return NextResponse.next(); } if (reqUrl.startsWith('/login')) { return NextResponse.next(); }; const loginUrl = new URL('/login', req.url); return NextResponse.redirect(loginUrl); }; export const config = { matcher: [ // 匹配所有路径,排除规则命中的路径 '/((?!_next/static|_next/image|favicon.ico|/api|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)', ], };
这个配置会自动跳过:
/_next/static、/_next/image开头的Next.js内部静态资源- favicon站点图标
/api开头的接口路径(如果接口需要走鉴权可删除这条规则)- 所有带静态资源后缀的文件(图片、字体、独立CSS/JS文件等)
所有业务页面路由都会正常走鉴权逻辑,后续新增路由不需要手动逐个添加配置。
方式2:在middleware逻辑内手动放行静态资源
如果不想写matcher正则,也可以在middleware逻辑最开头增加判断,命中静态资源路径直接放行:
// src/middleware.js import { NextResponse } from 'next/server'; export function middleware(req) { const { pathname } = req.nextUrl; // 开头直接放行所有静态资源和不需要鉴权的系统路径 if ( pathname.startsWith('/_next/') || pathname.startsWith('/api/') || // 接口不需要鉴权可保留,否则删除 pathname === '/favicon.ico' || pathname.includes('.') // 匹配所有带后缀的静态文件 ) { return NextResponse.next(); } // 原有鉴权逻辑保持不变 const userSession = req.headers.get('cookie'); const reqUrl = pathname; if (userSession?.includes('userToken')) { if (reqUrl.startsWith('/login')) { return NextResponse.redirect(new URL('/', req.url)); } return NextResponse.next(); } if (reqUrl.startsWith('/login')) { return NextResponse.next(); }; const loginUrl = new URL('/login', req.url); return NextResponse.redirect(loginUrl); };
两种方式效果完全一致,配置后静态资源会被正常返回,不会被重定向到登录页,空白和语法错误问题直接解决,同时所有新增的业务路由默认就会受鉴权逻辑保护,不需要额外配置。
内容的提问来源于stack exchange,提问作者Fer Toasted
相关产品推荐
相关产品推荐

