如何让Apollo GraphQL Codegen在Next.js前端项目中正常工作
Next.js + Apollo Client 类型提示配置问题解决
问题描述
我在使用Next.js,想给前端Apollo React查询加上TypeScript类型提示,但试了各种配置都没用。从src/__generated__/gql导入gql后,查询出现未知错误,悬停gql()时提示:The query argument is unknown! Please regenerate the types。
我的疑问:用Next.js是不是需要特殊配置?想通过《TypeScript with Apollo Client code gendocs》实现gql查询的类型化。另外我的Pothos schema全在pages/api/index.ts里,还不知道怎么拆分到多个文件。
示例查询代码
const CREATED_EVENT_QUERY = gql(` query EventById($id: mongoId!) { eventById(id: $id) { _id name description location{ coordinates } date eventApplicants{ name userId weight } link weights{ weight spotsAvailable{ name userId } } } } `); // Apollo Query const { loading, error, data } = useQuery(CREATED_EVENT_QUERY, { variables: { id: params.id } });
我试过的配置
Apollo官方推荐配置
import { CodegenConfig } from '@graphql-codegen/cli'; const config: CodegenConfig = { schema: 'http://localhost:3000/api', documents: ['*.ts'], generates: { './src/__generated__/': { preset: 'client', plugins: [], presetConfig: { gqlTagName: 'gql', } } }, ignoreNoDocuments: true, }; export default config;
The Guild的Next.js推荐配置
import type { CodegenConfig } from '@graphql-codegen/cli' const config: CodegenConfig = { // ... generates: { 'path/to/file.ts': { plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'], config: { reactApolloVersion: 3 } } } } export default config
两者组合配置
import { CodegenConfig } from '@graphql-codegen/cli'; const config: CodegenConfig = { schema: 'http://localhost:3000/api', documents: ['*.ts'], generates: { 'pages/api/index.ts': { plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'], config: { reactApolloVersion: 3 } } }, ignoreNoDocuments: true, }; export default config;
解决步骤
1. 修正代码生成核心配置
当前配置存在几个关键问题:
- 文档路径太宽泛:
['*.ts']会匹配所有ts文件,但pages/api下的schema文件无需作为查询文档处理,需指定前端查询路径并排除api目录 - 生成目标错误:第三个配置将生成文件写入
pages/api/index.ts,会覆盖原有schema文件,必须避免;官方client preset生成到src/__generated__目录是正确方向,但需优化配置 - schema获取方式:本地Pothos schema无需通过HTTP请求获取,直接指向本地文件更可靠
修正后的codegen.ts配置:
import { CodegenConfig } from '@graphql-codegen/cli'; const config: CodegenConfig = { // 直接读取本地Pothos schema文件,无需依赖本地服务启动 schema: './pages/api/index.ts', // 指定前端查询文件路径,排除api目录 documents: ['src/**/*.{ts,tsx}', 'pages/**/*.{ts,tsx}', '!pages/api/**/*'], generates: { './src/__generated__/': { preset: 'client', plugins: [], presetConfig: { gqlTagName: 'gql', // 自动生成类型化useQuery hook withHooks: true, }, config: { // 映射自定义标量类型到TS类型 scalars: { mongoId: 'string', }, }, }, }, ignoreNoDocuments: true, }; export default config;
2. 正确使用生成的类型化工具
必须从src/__generated__/gql导入gql和自动生成的类型化hook,无需手动编写查询字符串:
// 正确导入生成的工具 import { useEventByIdQuery } from '../__generated__/gql'; // 直接使用类型化hook,自动校验变量和返回数据类型 const { loading, error, data } = useEventByIdQuery({ variables: { id: params.id, }, });
若坚持手动编写查询字符串,也必须使用生成的gql标签,它会自动校验查询语法并提供类型提示。
3. 重新执行代码生成
确保安装所有依赖:
npm install --save-dev @graphql-codegen/cli @graphql-codegen/client-preset
在package.json添加脚本:
{ "scripts": { "codegen": "graphql-codegen", "codegen:watch": "graphql-codegen --watch" } }
执行生成命令:
npm run codegen
开发阶段可使用codegen:watch自动监听文件变化并重新生成类型。
4. Pothos schema拆分建议
当前schema集中在一个文件,可按业务类型拆分:
- 创建
pages/api/schemas/Event.ts定义Event类型及相关查询 - 创建
pages/api/schemas/User.ts定义User类型 - 在
pages/api/index.ts导入所有schema文件并合并到Pothos builder
示例拆分后的pages/api/schemas/Event.ts:
import { builder } from '../index'; builder.objectType('Event', { fields: (t) => ({ _id: t.exposeID('_id'), name: t.exposeString('name'), // 其他字段... }), }); builder.queryField('eventById', (t) => t.field({ type: 'Event', args: { id: t.arg({ type: 'mongoId', required: true }), }, resolve: async (_, { id }, { prisma }) => { return prisma.event.findUnique({ where: { id } }); }, }) );
在pages/api/index.ts导入:
import { builder } from '@pothos/core'; import './schemas/Event'; import './schemas/User'; // 其他配置... export default builder.toSchema();
内容的提问来源于stack exchange,提问作者Wayne
相关产品推荐
相关产品推荐

