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

自托管环境下能否运行Next.js新版middleware及相关报错如何解决

问题解答

1. 自托管环境下Next.js中间件的运行逻辑

Next.js的中间件无论部署在Vercel还是自托管环境都可以正常运行,它不会变成普通express中间件:

  • 不管你用next start自托管Node.js服务还是部署到其他平台,中间件默认都运行在Edge Runtime沙箱环境中,而非普通Node.js上下文
  • Edge Runtime有严格的API限制,禁用了eval、new Function等语法,同时不支持大部分Node.js原生API和依赖这些API的第三方包,这和你部署在哪里无关,只要用Edge Middleware就会受到这些限制

2. eval报错的原因与解决方案

你遇到的eval not allowed报错根本原因是标准jsonwebtoken包依赖了Edge Runtime禁用的语法,且你贴出的代码里包含MongoDB数据库查询逻辑,这类Node.js专属的数据库驱动也无法在Edge Runtime中运行,本质上你的代码场景并不适合使用Edge Middleware。
推荐你采用更适配的方案:放弃使用Edge Middleware,改用Node.js层的中间件封装:

  • 你之前使用的next-connect完全可以继续使用,Next.js没有废弃API路由的Node.js runtime支持,没有强制要求迁移Edge Middleware
  • 如果不想依赖next-connect,也可以自行封装高阶函数实现全局认证逻辑,示例如下:
// 封装认证中间件高阶函数
const withAuth = (handler) => async (req, res) => {
  const { access_token, refresh_token } = req.cookies;

  if (!access_token) {
    return handler(req, res);
  }

  try {
    // 你原来的认证逻辑完全可以直接复用,支持jsonwebtoken、MongoDB查询
    const { payload, expired } = verifyAccessToken(access_token);

    if (payload) {
      if (!payload.userId) {
        return res.status(401).send("User id is missing in JWT payload.");
      }
      const currentUser = await User.findById(payload.userId).lean();
      if (!currentUser) {
        return res.status(401).send("The user belonging to this token no longer exist.");
      }
      req.user = currentUser;
    }

    const { payload: refreshPayload } = verifyRefreshToken(refresh_token);
    const user = await User.findOne({ _id: refreshPayload?.userId });
    if (refreshPayload && user?.refreshToken === refresh_token && expired) {
      console.log("Refreshing access token");
      const newAccessToken = generateAccessToken(refreshPayload.userId);
      res.cookie("access_token", newAccessToken, {
        domain: "localhost",
        httpOnly: true,
        secure: process.env.NODE_ENV === "production",
        path: "/",
      });
    }

    return handler(req, res);
  } catch (error) {
    console.log(error);
    return handler(req, res);
  }
}

// 所有API路由导出时包裹即可
export default withAuth(async function handler(req, res) {
  // 原API路由逻辑
})

该方案完全运行在普通Node.js上下文,自托管和平台部署都兼容,没有Edge Runtime的各类限制。

3. 你现有Edge Middleware代码的问题

你现有代码中设置Cookie的逻辑是无效的:NextResponse.next().cookie()执行后你没有返回该响应实例,而是重新调用了NextResponse.next()返回了新的空响应,设置的Cookie会直接丢失。如果确实要使用Edge Middleware,需要调整为:

const response = NextResponse.next()
response.cookie('access_token', newAccessToken, {
  // 配置项
})
return response

内容的提问来源于stack exchange,提问作者JonasLevin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 11:06:02