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

Next.js 13 如何仅服务端导入next/headers?解决客户端调用报错

问题分析

你遇到的报错核心原因是:next/headers 中的 cookies API 仅能在服务端环境(Server Components、Server Actions、API 路由等)使用,而你的代码在客户端组件中直接导入了这个模块,导致客户端打包时触发了环境不兼容的错误。同时原代码里的环境判断注释写反了:typeof window === "undefined" 对应的是服务端环境,不是客户端。

解决方案

下面提供两种可行的实现方式,都能做到仅在服务端导入 next/headers:

方案一:动态导入+条件分支处理

在服务端逻辑分支内动态导入 cookies,确保客户端不会加载该模块:

import clientCookies from "js-cookie";

const myFetch = async (...args) => {
  let token;
  
  if (typeof window !== "undefined") {
    // 客户端环境:读取浏览器 Cookie
    token = clientCookies.get("authToken");
  } else {
    // 服务端环境:动态导入并读取服务端 Cookie
    const { cookies } = await import("next/headers");
    const serverCookies = cookies();
    token = serverCookies.get("authToken")?.value;
  }

  // 合并原有请求头,避免覆盖用户传入的其他头信息
  args[1] = args[1] || {};
  args[1].headers = {
    ...args[1].headers,
    Authorization: token ? `bearer ${token}` : undefined,
  };

  const res = await fetch(...args);
  const data = await res.json();
  return data;
};

export default myFetch;

方案二:拆分客户端/服务端专用函数

将客户端和服务端的逻辑完全分离,分别导出后根据环境选择使用:

// client-fetch.js(仅客户端使用)
import clientCookies from "js-cookie";

export const clientFetch = async (...args) => {
  const token = clientCookies.get("authToken");
  args[1] = args[1] || {};
  args[1].headers = {
    ...args[1].headers,
    Authorization: token ? `bearer ${token}` : undefined,
  };
  const res = await fetch(...args);
  return res.json();
};
// server-fetch.js(仅服务端使用)
import { cookies } from "next/headers";

export const serverFetch = async (...args) => {
  const serverCookies = cookies();
  const token = serverCookies.get("authToken")?.value;
  args[1] = args[1] || {};
  args[1].headers = {
    ...args[1].headers,
    Authorization: token ? `bearer ${token}` : undefined,
  };
  const res = await fetch(...args);
  return res.json();
};
// index.js(统一导出入口)
let myFetch;
if (typeof window !== "undefined") {
  myFetch = (await import("./client-fetch.js")).clientFetch;
} else {
  myFetch = (await import("./server-fetch.js")).serverFetch;
}

export default myFetch;
额外注意事项
  • 处理 token 不存在的情况,避免生成 bearer undefined 这种无效的授权头
  • 不要直接覆盖 args[1].headers,通过扩展运算符合并原有头信息,防止丢失用户传入的其他请求头
  • 确保环境判断逻辑正确:typeof window !== "undefined" 才是客户端环境

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 17:43:17