使用Next.js Middleware时遭遇Uncaught SyntaxError: Unexpected token '<'错误
问题:Next.js中间件结合Zustand校验登录时出现资源加载错误
我用Next.js中间件做登录校验,逻辑是通过Zustand store里的loggedIn布尔值判断用户是否登录,未登录就重定向到登录页,代码如下:
import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; import { useAuthStore } from "./zustand/store"; export function middleware(request: NextRequest) { const loggedIn = useAuthStore.getState().loggedIn; if (!loggedIn) { const url = request.nextUrl.clone(); url.pathname = "/login"; return NextResponse.rewrite(url); } else { return NextResponse.rewrite(request.nextUrl.clone()); } }
但运行后浏览器抛出一堆类似的错误:
react-refresh.js?ts=1661359264454:1 Uncaught SyntaxError: Unexpected token '<' (at react-refresh.js?ts=1661359264454:1:1) 18:41:04.842 webpack.js?ts=1661359264454:1 Uncaught SyntaxError: Unexpected token '<' (at webpack.js?ts=1661359264454:1:1) 18:41:04.842 main.js?ts=1661359264454:1 Uncaught SyntaxError: Unexpected token '<' (at main.js?ts=1661359264454:1:1) 18:41:04.909 _app.js?ts=1661359264454:1 Uncaught SyntaxError: Unexpected token '<' (at _app.js?ts=1661359264454:1:1) 18:41:04.924 index.js?ts=1661359264454:1 Uncaught SyntaxError: Unexpected token '<' (at index.js?ts=1661359264454:1:1) 18:41:04.925 _buildManifest.js?ts=1661359264454:1 Uncaught SyntaxError: Unexpected token '<' (at _buildManifest.js?ts=1661359264454:1:1) 18:41:04.925 _ssgManifest.js?ts=1661359264454:1 Uncaught SyntaxError: Unexpected token '<' (at _ssgManifest.js?ts=1661359264454:1:1)
问题原因
- 资源请求被错误拦截:默认情况下Next.js中间件会拦截所有请求,包括静态资源、webpack打包生成的JS文件。当未登录时,这些资源请求被
rewrite到/login页面的HTML内容,浏览器尝试把HTML当成JS解析,就会出现Unexpected token '<'错误。 - Zustand状态无法在服务器端使用:中间件运行在Edge Runtime(服务器端),而Zustand是客户端状态管理工具,服务器端无法获取客户端的实时登录状态,
getState()拿到的只是初始默认值,逻辑完全失效。 - 错误使用rewrite:
rewrite是服务器内部重写请求,浏览器地址栏不会变化,不适合登录跳转场景,应该用redirect让浏览器主动跳转。
解决方案
1. 限制中间件作用范围
配置matcher,只让中间件拦截需要登录验证的页面路由,避免影响静态资源:
export const config = { matcher: ['/dashboard/:path*', '/profile/:path*'], // 按需修改成你的受保护路由 };
2. 替换rewrite为redirect,修正跳转逻辑
import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; export function middleware(request: NextRequest) { // 注意:这里不能用Zustand,要换成服务器端可获取的登录凭证 const authToken = request.cookies.get('auth-token'); const loggedIn = !!authToken; // 排除登录页,避免死循环 if (!loggedIn && request.nextUrl.pathname !== '/login') { const url = request.nextUrl.clone(); url.pathname = '/login'; return NextResponse.redirect(url); } return NextResponse.next(); } // 配置受保护路由 export const config = { matcher: ['/dashboard/:path*', '/profile/:path*'], };
3. 改用服务器端可验证的登录方式
放弃用Zustand做登录校验,改用Cookie、Session或JWT:
- 用户登录成功后,后端设置带有登录凭证的Cookie(比如
auth-token) - 中间件从请求Cookie中读取凭证,验证有效性来判断登录状态
内容的提问来源于stack exchange,提问作者Bowis
相关产品推荐
相关产品推荐

