Next.js中authLink、httpLink与GraphQL订阅集成问题求助
解决Apollo Client中authLink与splitLink协同工作的问题
我明白你遇到的困扰了——在Next.js SSR环境下配置Apollo Client时,authLink没法正常生效,还碰到了终止链接的报错。这其实是链路顺序搞反导致的,我来帮你梳理清楚:
问题根源
splitLink属于终止链接(terminating link),它的作用是直接处理请求(要么通过httpLink发送HTTP请求,要么通过wsLink建立WebSocket连接),是整个请求链路的终点。如果你把authLink放在splitLink后面,请求已经被终止链接处理完了,authLink根本没有机会修改请求头,而且还会触发那个“concat终止链接无效”的报错。
正确的逻辑应该是:先让请求经过authLink添加鉴权头,再进入splitLink选择传输方式。另外还要注意,WebSocket连接初始化时也需要携带token,不然订阅请求会鉴权失败。
修改后的完整配置
import {ApolloClient, ApolloLink, createHttpLink, InMemoryCache, split} from "@apollo/client" import {setContext} from "@apollo/client/link/context" import { WebSocketLink } from "@apollo/client/link/ws" import {getMainDefinition} from "@apollo/client/utilities"; const httpLink = createHttpLink({ uri: "http://localhost:4000/graphql", }) // 处理WebSocket链接,同时添加鉴权参数 const wsLink = process.browser ? new WebSocketLink({ uri: 'ws://localhost:4000/graphql', options: { reconnect: true, // 建立WebSocket连接时携带token connectionParams: () => { const token = localStorage.getItem('token') return { authorization: token } } } }) : null // 处理HTTP请求的鉴权头,同时兼容SSR环境(避免localStorage报错) const authLink = setContext((_, { headers }) => { // 仅在浏览器环境下获取token,SSR时跳过 const token = process.browser ? localStorage.getItem('token') : null return { headers: { ...headers, authorization: token ? token : '' } } }) // 创建splitLink:选择HTTP或WebSocket传输 const splitLink = process.browser ? split( ({ query }) => { const definition = getMainDefinition(query) return ( definition.kind === 'OperationDefinition' && definition.operation === 'subscription' ) }, wsLink, httpLink ) : httpLink // 关键:链路顺序是authLink在前,splitLink在后 const client = new ApolloClient({ link: ApolloLink.from([authLink, splitLink]), cache: new InMemoryCache(), }); export default client;
关键修改点说明
- 链路顺序调整:用
ApolloLink.from([authLink, splitLink])让请求先经过authLink处理头信息,再进入splitLink选择传输方式,这样不管是HTTP请求还是WebSocket订阅,都能带上鉴权头。 - WebSocket鉴权补充:在wsLink的
connectionParams里添加token,因为WebSocket是长连接,初始化时就需要传递鉴权信息,后续的订阅请求会复用这个连接的鉴权。 - SSR环境兼容:在获取localStorage时加上
process.browser判断,避免Next.js在服务端渲染时因为没有localStorage而抛出错误。
这样配置后,authLink就能正常生效,不管是查询、突变还是订阅请求,都会正确携带你的token了。
内容的提问来源于stack exchange,提问作者alienbuild
相关产品推荐
相关产品推荐

