NextJS+Apollo+GraphQL使用Fragment触发500错误求助
解决Apollo复用GraphQL Fragment时出现500错误的问题
我尝试在GraphQL查询中复用基础Fragment,通过${NEXT_SEO_FRAGMENT}变量插入时触发ApolloError,提示Response not successful: Received status code 500。直接写字段的查询可正常运行,但使用Fragment就报错。
报错代码
import { getApolloClient } from "../apollo-client"; import gql from 'graphql-tag' import { Locale } from "../types"; const NEXT_SEO_FRAGMENT = gql` fragment NextSeoFields on NextSeoType { seoDescription seoTitle } `; export async function getHomeEntrys(locale: Locale) { const apolloClient = getApolloClient(); const language = locale; const { data } = await apolloClient.query({ query: gql` query pages($language: LanguageCodeFilterEnum!) { pages(where: { language: $language }) { edges { node { title content slug language { code locale } id isFrontPage nextSeo { ...NextSeoFields } } } } } ${NEXT_SEO_FRAGMENT} `, variables: { language, }, }); return data?.pages.edges }
正常运行的代码(未使用Fragment)
import { getApolloClient } from "../apollo-client"; import gql from 'graphql-tag' import { Locale } from "../types"; export async function getHomeEntrys(locale: Locale) { const apolloClient = getApolloClient(); const language = locale; const { data } = await apolloClient.query({ query: gql` query pages($language: LanguageCodeFilterEnum!) { pages(where: { language: $language }) { edges { node { title content slug language { code locale } id isFrontPage nextSeo { seoDescription seoTitle } } } } } `, variables: { language, }, }); return data?.pages.edges }
问题原因
gql标签返回的是解析后的GraphQL AST(DocumentNode对象),而非字符串。直接在模板字符串中用${NEXT_SEO_FRAGMENT}插入该对象时,会被强制转换为[object Object],导致最终的查询语法完全错误,服务器因此返回500状态码。
解决方案
方案1:将Fragment与查询放在同一个gql模板中
把Fragment定义直接写在查询语句的同一gql标签内,确保AST被正确解析:
import { getApolloClient } from "../apollo-client"; import gql from 'graphql-tag' import { Locale } from "../types"; export async function getHomeEntrys(locale: Locale) { const apolloClient = getApolloClient(); const language = locale; const { data } = await apolloClient.query({ query: gql` fragment NextSeoFields on NextSeoType { seoDescription seoTitle } query pages($language: LanguageCodeFilterEnum!) { pages(where: { language: $language }) { edges { node { title content slug language { code locale } id isFrontPage nextSeo { ...NextSeoFields } } } } } `, variables: { language }, }); return data?.pages.edges }
方案2:用gql标签合并独立Fragment与查询
如果需要单独定义Fragment以复用,可通过gql标签直接插入的方式合并AST:
import { getApolloClient } from "../apollo-client"; import gql from 'graphql-tag' import { Locale } from "../types"; const NEXT_SEO_FRAGMENT = gql` fragment NextSeoFields on NextSeoType { seoDescription seoTitle } `; export async function getHomeEntrys(locale: Locale) { const apolloClient = getApolloClient(); const language = locale; const { data } = await apolloClient.query({ query: gql` ${NEXT_SEO_FRAGMENT} query pages($language: LanguageCodeFilterEnum!) { pages(where: { language: $language }) { edges { node { title content slug language { code locale } id isFrontPage nextSeo { ...NextSeoFields } } } } } `, variables: { language }, }); return data?.pages.edges }
注意:部分GraphQL服务器要求Fragment定义必须出现在查询语句之前,因此建议将Fragment放在查询上方。
内容的提问来源于stack exchange,提问作者Carol Privat
相关产品推荐
相关产品推荐

