升级@apollo/client至3.8.x时出现FIELD读取未定义错误求助
解决Apollo Client 3.8.x升级后「Cannot read properties of undefined (reading 'FIELD')」错误
这个错误源于3.8.x版本对订阅链路的依赖、初始化逻辑做了变更,导致旧协议(subscriptions-transport-ws)与新协议(graphql-ws)的客户端配置出现兼容性冲突,以下是具体解决思路:
1. 锁定兼容的依赖版本
Apollo Client 3.8.x对相关依赖的版本要求有更新,需确保以下包的版本匹配:
- 新WebSocket协议(graphql-ws):安装
^5.11.0及以上版本 - 旧WS协议(subscriptions-transport-ws):保持
^0.11.0及以上版本 - GraphQL核心包:安装
^16.6.0及以上版本
执行命令更新依赖:
npm install graphql@^16.6.0 graphql-ws@^5.11.0 subscriptions-transport-ws@^0.11.0
2. 修正旧协议客户端的链路配置
3.8.x中@apollo/client/link/ws已被废弃,旧协议客户端必须明确使用subscriptions-transport-ws提供的WebSocketLink,且链路拆分逻辑要正确:
import { ApolloClient, InMemoryCache, split, HttpLink } from '@apollo/client'; import { getMainDefinition } from '@apollo/client/utilities'; // 注意:旧协议的WebSocketLink来自subscriptions-transport-ws,而非@apollo/client import { WebSocketLink } from 'subscriptions-transport-ws'; // 旧协议客户端配置 const oldHttpLink = new HttpLink({ uri: '你的旧服务器HTTP地址' }); const oldWsLink = new WebSocketLink({ uri: '你的旧服务器WS地址', options: { reconnect: true }, }); // 拆分HTTP和WS链路 const oldSplitLink = split( ({ query }) => { const definition = getMainDefinition(query); return ( definition.kind === 'OperationDefinition' && definition.operation === 'subscription' ); }, oldWsLink, oldHttpLink ); const oldClient = new ApolloClient({ link: oldSplitLink, cache: new InMemoryCache(), });
3. 规范新协议客户端的初始化
新协议客户端需使用@apollo/client/link/subscriptions提供的GraphQLWsLink,确保初始化逻辑符合3.8.x要求:
import { ApolloClient, InMemoryCache, HttpLink, split } from '@apollo/client'; import { getMainDefinition } from '@apollo/client/utilities'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { createClient } from 'graphql-ws'; // 新协议客户端配置 const newHttpLink = new HttpLink({ uri: '你的新服务器HTTP地址' }); const newWsLink = new GraphQLWsLink(createClient({ url: '你的新服务器WS地址', })); const newSplitLink = split( ({ query }) => { const definition = getMainDefinition(query); return ( definition.kind === 'OperationDefinition' && definition.operation === 'subscription' ); }, newWsLink, newHttpLink ); const newClient = new ApolloClient({ link: newSplitLink, cache: new InMemoryCache(), });
4. 禁用自动订阅链路初始化
3.8.x新增了自动检测订阅链路的逻辑,可能导致两个客户端的链路冲突,需显式关闭该特性:
const client = new ApolloClient({ // ...其他配置 defaultOptions: { watchQuery: { subscribeToMore: { autoInitialize: false, }, }, }, });
5. 排查链路混用问题
确保两个客户端的链路配置完全隔离,不要混用新旧协议的链路类(比如不要给旧协议客户端用GraphQLWsLink,反之亦然),避免AST枚举(如FIELD)的引用冲突。
内容的提问来源于stack exchange,提问作者CanIHazCookieNow
相关产品推荐
相关产品推荐

