如何为apollo-codegen添加本地@client Schema扩展?
我之前也踩过这个坑!apollo-codegen默认只会抓取服务端的GraphQL Schema,完全不会自动识别你用apollo-link-state添加的本地扩展字段,所以才会报“Cannot query field 'foo' on type 'Query'”的错误。要解决这个问题,核心思路是把服务端Schema和你的客户端本地扩展合并成一个完整的Schema,再让codegen基于这个合并后的Schema生成类型注解。
下面是具体的操作步骤,分两种常用方案:
方案一:手动合并Schema(适配所有版本)
导出服务端Schema到本地
用apollo-codegen的下载命令把服务端Schema存到本地文件,比如:apollo-codegen download-schema https://你的GraphQL服务地址/graphql --output schema.json也可以导出为
.graphql格式,把--output改成schema.graphql即可。单独存放客户端扩展的TypeDef
创建一个专门的客户端Schema文件,比如client-schema.graphql,把你的扩展代码放进去:extend type Query { foo: String }编写脚本合并两个Schema
借助@graphql-tools/schema工具来合并,先安装依赖:npm install @graphql-tools/schema @graphql-tools/load @graphql-tools/graphql-file-loader @graphql-tools/json-file-loader graphql --save-dev然后创建
merge-schemas.js脚本:const { mergeSchemas, printSchema } = require('@graphql-tools/schema'); const { loadSchemaSync } = require('@graphql-tools/load'); const { GraphQLFileLoader } = require('@graphql-tools/graphql-file-loader'); const { JsonFileLoader } = require('@graphql-tools/json-file-loader'); const fs = require('fs'); // 加载服务端和客户端Schema const serverSchema = loadSchemaSync('./schema.json', { loaders: [new JsonFileLoader()] }); const clientSchema = loadSchemaSync('./client-schema.graphql', { loaders: [new GraphQLFileLoader()] }); // 合并并输出完整Schema const mergedSchema = mergeSchemas({ schemas: [serverSchema, clientSchema] }); fs.writeFileSync('./merged-schema.graphql', printSchema(mergedSchema));运行脚本生成合并后的Schema:
node merge-schemas.js让codegen使用合并后的Schema
修改你的codegen命令,指定用本地的merged-schema.graphql:apollo-codegen generate ./src/**/*.js --schema ./merged-schema.graphql --output ./src/graphql/types.flow.js
方案二:用Apollo CLI配置自动合并(适配新版Apollo)
如果你用的是@apollo/cli(较新的版本),可以通过配置文件让CLI自动合并服务端和客户端Schema:
创建apollo.config.js配置文件
在项目根目录新建这个文件,内容如下:module.exports = { client: { service: { name: '你的服务名称', url: 'https://你的GraphQL服务地址/graphql', }, // 指定包含客户端的TypeDef文件 includes: [ './src/**/*.js', './src/client-schema.graphql' ], }, };直接运行codegen命令
不用手动下载和合并,直接执行:apollo client:codegen ./src/graphql/types.flow.js --target flowCLI会自动拉取服务端Schema,并合并你指定的客户端扩展,然后生成正确的Flow注解。
两种方案都能解决问题,我个人更推荐方案二,因为不用维护额外的合并脚本,更省心。另外要注意,你的查询里的@client指令一定要保留,这样Apollo客户端和codegen都能正确识别这是本地字段。
内容的提问来源于stack exchange,提问作者Mike Marcacci

