Next.js服务端调用GraphQL如何获取Cookie中的Token
这个问题我之前也碰到过,核心问题是你当前的token获取逻辑是在模块初始化阶段执行的,这时候服务端还没拿到请求上下文(ctx),而且服务端没有浏览器的document对象,所以js-cookie根本拿不到服务端的Cookie。解决的关键是把token的获取和Apollo Client的初始化逻辑绑定到next-with-apollo提供的ctx参数上——它的回调函数其实是可以接收ctx的!
修改步骤和核心逻辑
- 把token获取逻辑移到withApollo的回调函数内:这个回调会接收包含
ctx和initialState的对象,服务端渲染时ctx里的req对象包含了请求的Cookie信息。 - 区分服务端和客户端的Cookie获取方式:
- 服务端:从
ctx.req.headers.cookie解析token(需要用cookie库来解析Cookie字符串) - 客户端:继续使用
js-cookie获取token
- 服务端:从
- 动态创建Apollo Link:确保每次初始化Apollo Client时,都能根据当前环境拿到正确的token并设置请求头。
修改后的完整代码
import { ApolloClient } from 'apollo-client' import { InMemoryCache } from 'apollo-cache-inmemory' import withApollo from 'next-with-apollo' import { createHttpLink } from 'apollo-link-http' import fetch from 'isomorphic-unfetch' import cookie from 'js-cookie' // 服务端解析Cookie需要用到这个包,记得先安装:npm install cookie import cookieParser from 'cookie' const GRAPHQL_URL = 'https://myurl.com' export default withApollo(({ ctx, initialState }) => { // 区分服务端和客户端获取token let token if (typeof window === 'undefined') { // 服务端:从req.headers.cookie解析token const serverCookie = ctx.req?.headers?.cookie if (serverCookie) { const parsedCookies = cookieParser.parse(serverCookie) token = parsedCookies.token } } else { // 客户端:用js-cookie获取token token = cookie.get('token') } // 动态创建带token的http link const link = createHttpLink({ fetch, uri: GRAPHQL_URL, headers: { authorization: token ? `Bearer ${token}` : '', }, }) return new ApolloClient({ link, cache: new InMemoryCache().restore(initialState || {}), }) })
关键细节解释
- 服务端Cookie解析:服务端的Cookie是存在请求头的
cookie字段里的字符串,需要用cookie库的parse方法转换成对象才能拿到token。同时要做可选链判断(ctx.req?.headers?.cookie),避免请求头没有Cookie时报错。 - withApollo的回调参数:
next-with-apollo的回调函数会接收一个包含ctx和initialState的对象,服务端渲染时ctx就是Next.js的请求上下文,包含req、res等信息。 - 动态Link创建:把Link的创建放到回调里,确保每次初始化Apollo Client时都能拿到当前请求的token,不管是服务端还是客户端渲染场景。
注意事项
- 确保安装了
cookie包:服务端解析Cookie需要用到它,执行npm install cookie或yarn add cookie即可。 - 验证token存在性:如果token不存在,请求头的
authorization会是空字符串,后端需要处理未授权的情况。
内容的提问来源于stack exchange,提问作者Sooraj




