You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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)

问题原因

  1. 资源请求被错误拦截:默认情况下Next.js中间件会拦截所有请求,包括静态资源、webpack打包生成的JS文件。当未登录时,这些资源请求被rewrite到/login页面的HTML内容,浏览器尝试把HTML当成JS解析,就会出现Unexpected token '<'错误。
  2. Zustand状态无法在服务器端使用:中间件运行在Edge Runtime(服务器端),而Zustand是客户端状态管理工具,服务器端无法获取客户端的实时登录状态,getState()拿到的只是初始默认值,逻辑完全失效。
  3. 错误使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 21:45:25