Next.js客户端拼接GraphCMS远程Schema时遇watchQuery函数错误求助
解决Next.js客户端拼接GraphCMS端点时的
watchQuery is not a function错误 看起来你是把服务端Schema聚合的逻辑错放到客户端Apollo Client初始化里了——这就是问题的核心!makeRemoteExecutableSchema和mergeSchemas是用来在服务端搭建GraphQL网关的工具,客户端的Apollo Client根本不认识这些Schema级别的操作,自然找不到watchQuery方法。下面给你两种可行的解决思路:
思路一:客户端直接路由请求到不同端点(无需Schema合并)
如果不想额外搭建服务端网关,可以用Apollo Client的split方法,根据请求的内容把查询路由到对应的GraphCMS端点:
// initApollo.js import { ApolloClient, InMemoryCache, HttpLink, split } from '@apollo/client'; import { getMainDefinition } from '@apollo/client/utilities'; // 定义两个GraphCMS端点的HttpLink const cmsLink1 = new HttpLink({ uri: 'https://your-first-graphcms-endpoint.com' }); const cmsLink2 = new HttpLink({ uri: 'https://your-second-graphcms-endpoint.com' }); // 根据查询的内容判断走哪个端点 const splitLink = split( ({ query }) => { const definition = getMainDefinition(query); // 示例:如果查询的是"posts"字段,走第一个端点;其他走第二个 return ( definition.kind === 'OperationDefinition' && definition.selectionSet.selections.some(sel => sel.name.value === 'posts') ); }, cmsLink1, cmsLink2 ); export default function initApollo() { return new ApolloClient({ ssrMode: typeof window === 'undefined', link: splitLink, cache: new InMemoryCache(), }); }
思路二:在Next.js服务端搭建GraphQL网关(推荐多端点聚合场景)
如果需要真正合并多个GraphCMS的Schema(比如解决字段冲突、统一查询入口),可以在Next.js的API路由里搭建一个网关:
1. 创建网关API路由
// pages/api/graphql.js import { ApolloServer } from 'apollo-server-micro'; import { makeRemoteExecutableSchema, mergeSchemas, introspectSchema } from '@graphql-tools/schema'; import { HttpLink } from 'apollo-link-http'; import fetch from 'node-fetch'; async function buildGatewaySchema() { // 拉取并处理第一个GraphCMS端点的Schema const cmsLink1 = new HttpLink({ uri: 'https://your-first-graphcms-endpoint.com', fetch }); const cmsSchema1 = await introspectSchema(cmsLink1); const executableSchema1 = makeRemoteExecutableSchema({ schema: cmsSchema1, link: cmsLink1 }); // 处理第二个GraphCMS端点的Schema const cmsLink2 = new HttpLink({ uri: 'https://your-second-graphcms-endpoint.com', fetch }); const cmsSchema2 = await introspectSchema(cmsLink2); const executableSchema2 = makeRemoteExecutableSchema({ schema: cmsSchema2, link: cmsLink2 }); // 合并两个可执行Schema(字段冲突时可以在这里自定义resolver处理) return mergeSchemas({ schemas: [executableSchema1, executableSchema2], }); } let apolloServer; export default async function handler(req, res) { if (!apolloServer) { const gatewaySchema = await buildGatewaySchema(); apolloServer = new ApolloServer({ schema: gatewaySchema }); await apolloServer.start(); } await apolloServer.createHandler({ path: '/api/graphql' })(req, res); } // 禁用Next.js默认的body解析,交给Apollo Server处理 export const config = { api: { bodyParser: false, }, };
2. 客户端指向本地网关
修改你的initApollo.js,让客户端请求这个本地网关端点:
// initApollo.js import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client'; export default function initApollo() { return new ApolloClient({ ssrMode: typeof window === 'undefined', link: new HttpLink({ uri: '/api/graphql' }), cache: new InMemoryCache(), }); }
额外注意:版本兼容性
确保你的依赖包版本统一:现在Apollo Client的官方包是@apollo/client,旧版的apollo-client已经不再维护,和@graphql-tools/schema这类工具可能存在兼容性问题,建议把依赖都升级到最新稳定版。
内容的提问来源于stack exchange,提问作者Will Meier
相关产品推荐
相关产品推荐

