升级@nestjs/graphql@11后Apollo联邦子图非共享字段异常求助
问题背景
采用Monorepo架构,所有GraphQL对象类型集中在公共包定义导出,子图基于ApolloFederationDriver开发,网关使用ApolloGatewayDriver。升级至@apollo/server搭配@nestjs/graphql@11 + @nestjs/apollo@11后出现以下异常:
- 子图组合时,未引入某实体的子图A被提示存在子图B对象类型的非共享字段
- 发现只要某个
ObjectType通过@Field(() => AnotherObjectType)引用了其他对象类型,AnotherObjectType会被自动纳入所有子图的Schema,无论该子图是否实际用到这个类型
比如somethings-application未使用User模型,却依然触发User非共享字段的报错,而posts-application因主动使用User报错属于预期情况。
核心原因
这是@nestjs/graphql@11版本代码优先模式下的自动类型发现机制变更:当公共包中的类型被任意子图引用时,Nest会递归扫描所有关联的ObjectType并将其加入当前子图Schema,无论该子图是否需要这些类型。这种自动引入行为导致无关类型进入子图定义,进而在联邦组合时触发非共享字段的校验错误。
解决方案
1. 显式指定子图包含的类型
在子图的GraphQLModule.forRoot配置中,通过include选项明确声明当前子图需要的解析器和类型,阻断自动引入无关类型:
GraphQLModule.forRoot<ApolloFederationDriverConfig>({ driver: ApolloFederationDriver, autoSchemaFile: true, include: [SomethingResolver, SomethingType], // 仅包含当前子图依赖的资源 });
2. 拆分公共包类型结构
将不同子图专属的类型拆分到各自的子包中,公共包仅保留跨子图共享的联邦实体(带@Key装饰器的类型)。让每个子图仅依赖自身需要的类型包,从根源避免无关类型被引入。
3. 用@Ignore排除子图无关字段
若无法拆分类型,可在公共包的ObjectType中,对仅属于特定子图的字段添加@Ignore()装饰器,其他子图生成Schema时会自动忽略这些字段:
import { ObjectType, Field, Ignore } from '@nestjs/graphql'; @ObjectType() export class User { @Field() id: string; // 仅子图B需要的字段,其他子图生成Schema时忽略 @Ignore() @Field() privateField: string; }
4. 禁用自动类型扫描,手动生成Schema
关闭autoSchemaFile的自动扫描逻辑,手动生成并指定仅包含必要类型的Schema:
GraphQLModule.forRoot<ApolloFederationDriverConfig>({ driver: ApolloFederationDriver, schema: await generateSchema({ resolvers: [SomethingResolver], types: [SomethingType], }), });
验证
修改配置后重启子图和网关,检查组合后的Schema是否仅包含各子图实际需要的类型,确认非共享字段的报错是否消除。
内容的提问来源于stack exchange,提问作者MrSquaare

