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

Next.js 13如何在HTML渲染前通过中间件获取客户端Cookie?

在Next.js 13中HTML渲染前获取Cookie的正确方式

核心问题解答

  1. 能不能在HTML渲染前获取Cookie?
    完全可以。Next.js 13提供了服务器端获取Cookie的能力,这个过程发生在HTML渲染之前,服务器组件(Server Component)或中间件(Middleware)都能实现。

  2. 使用window对象可行吗?
    绝对不行。window是浏览器端全局对象,在服务器端渲染(SSR)、静态生成(SSG)或中间件运行阶段不存在,直接调用会抛出错误。只有在客户端组件(Client Component)的useEffect钩子或用户交互事件中,才能通过window.document.cookie访问Cookie,但这已经是HTML渲染完成后的操作了。


你的代码问题修正

1. 中间件(middleware.ts)问题修复

你的中间件存在无返回数据、Cookie值设置错误、缺少标准结构等问题,修正后代码如下:

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

export async function middleware(request: NextRequest) {
  const response = NextResponse.next();

  // 避免重复请求:如果已有regionCode Cookie,直接返回
  const existingRegion = request.cookies.get('regionCode');
  if (existingRegion) {
    return response;
  }

  try {
    // 从请求对象直接获取用户IP(Edge环境下更准确)
    const userIp = request.ip || 'unknown';
    // 请求IP地理位置接口
    const geoRes = await fetch(`https://ipapi.co/${userIp}/json/`, {
      next: { revalidate: 86400 } // 缓存一天,减少接口调用次数
    });
    const geoData = await geoRes.json();
    
    // 提取地区信息(根据接口返回字段调整)
    const regionCode = geoData.region || geoData.city || 'default';
    // 设置Cookie并配置参数
    response.cookies.set('regionCode', regionCode, {
      maxAge: 86400 * 7, // 有效期7天
      path: '/',
      httpOnly: true, // 可选,提升安全性防止XSS
      secure: process.env.NODE_ENV === 'production' // 生产环境强制HTTPS传输
    });

    return response;
  } catch (err) {
    console.error('获取地理位置失败:', err);
    // 出错时设置默认地区
    response.cookies.set('regionCode', 'default', { maxAge: 86400 * 7, path: '/' });
    return response;
  }
}

// 指定中间件作用范围:所有路由
export const config = {
  matcher: '/:path*',
};

2. 页面组件(page.tsx)优化

你的页面代码基本正确,可增加容错处理避免undefined情况:

import { cookies } from 'next/headers';

async function getData() {
  const nextCookies = cookies();
  try {
    const cityToken = nextCookies.get('regionCode');
    return cityToken?.value || 'default';
  } catch (e) {
    console.log(e);
    return 'default';
  }
}

export default async function Page() {
  // 两种方式均可获取Cookie:直接调用cookies()或通过异步函数getData
  const cityToken = cookies().get('regionCode')?.value || 'default';
  // 或者 const cityToken = await getData();

  console.log('当前地区Cookie:', cityToken);

  return (
    <div>
      <p>当前地区: {cityToken}</p>
    </div>
  );
}

关键知识点总结

  • 服务器组件(Server Component):通过next/headers提供的cookies()函数直接获取Cookie,该过程在服务器端执行,发生在HTML渲染之前,能拿到中间件设置的最新Cookie。
  • 中间件(Middleware):通过request.cookies读取请求中的Cookie,通过NextResponse.cookies.set()设置响应Cookie,中间件执行顺序在页面渲染之前,所以页面渲染时Cookie已存在。
  • 客户端组件(Client Component):若必须在客户端处理Cookie,只能在useEffect或用户交互事件中使用document.cookie,但这是渲染完成后的操作,不符合“渲染前获取”的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:50:36