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

Next.js生产环境设置Cookie后Middleware无法读取需刷新页面问题

问题描述

在Next.js项目中,登录页面使用cookies-next库设置名为user的Cookie后,通过router.push跳转到目标页面,生产环境下Middleware无法读取该Cookie,必须刷新页面才能正常读取;但开发环境(npm run dev)无此问题。

设置Cookie的代码

import { getCookies, setCookie, deleteCookie, hasCookie } from 'cookies-next';
import { useRouter } from 'next/router';

export default function LoginPage() {

    const router = useRouter()

    const login = () => {
        if (hasCookie('user')) {
            router.push('/');
            return;
        }

        setCookie('user', 'DHamidi-RandomValue')
        router.push('/');
    }

    return <div className="layout">
        <h2>Login</h2>

        <button onClick={login}>
            Add User Info To Cookie.
        </button>
    </div>
}

Middleware读取Cookie的代码

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
    if (request.cookies.has('user')) return NextResponse.next()
    
    return NextResponse.redirect(new URL('/login', request.nextUrl.clone()))
}

export const config = {
    matcher: '/admin/:path*',
}

注:问题仅在生产环境(npm run build => npm run start)出现。

原因分析

这是因为Next.js生产环境下的客户端路由跳转(router.push)属于SPA式导航,不会触发完整的HTTP请求到服务器,而Middleware是运行在服务器端的,它只能读取浏览器在HTTP请求头中携带的Cookie。

当你在客户端用cookies-next设置Cookie后直接调用router.push跳转,此时只是客户端内部的页面切换,浏览器不会向服务器发送新请求,Middleware自然无法获取到刚设置的Cookie——只有刷新页面时,浏览器才会在HTTP请求头中带上所有当前有效的Cookie,Middleware才能读取到。

开发环境中,Next.js的热重载机制或客户端路由的行为逻辑和生产环境存在差异,可能隐式触发了类似请求的同步行为,所以没有出现这个问题。

解决方案

有两种常见方案可以解决这个问题:

  • 改用服务器端设置Cookie后跳转
    把登录逻辑放到API路由中,在API里设置Cookie并返回跳转响应,这样浏览器会在后续请求中自动带上Cookie:

    // pages/api/login.ts
    import { NextApiRequest, NextApiResponse } from 'next';
    import { setCookie } from 'cookies-next';
    
    export default function handler(req: NextApiRequest, res: NextApiResponse) {
      setCookie('user', 'DHamidi-RandomValue', { req, res });
      res.redirect('/admin');
    }
    

    登录页面的按钮改为调用该API,而非客户端设置Cookie后跳转。

  • 改用window.location.href触发完整跳转
    如果坚持在客户端设置Cookie,可以用window.location.href替代router.push,这会触发完整的页面刷新,浏览器会带上新设置的Cookie:

    const login = () => {
        if (hasCookie('user')) {
            window.location.href = '/';
            return;
        }
    
        setCookie('user', 'DHamidi-RandomValue')
        window.location.href = '/';
    }
    

    缺点是会丢失SPA跳转的流畅性,但能确保Middleware读取到最新的Cookie。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 11:32:48