基于NestJS GraphQL模块的Apollo Gateway如何保存Schema文件?
解决NestJS Apollo Gateway生成并保存组合Schema的方案
核心问题原因
IntrospectAndCompose是异步拉取并组合子图Schema的模式,onModuleInit钩子执行时,Gateway还未完成子图的 introspection 和Schema组合流程,因此GraphQLSchemaHost无法获取到已生成的最终Schema。
可行方案
方案一:监听Apollo Gateway的onSchemaChange事件
Apollo Gateway内置了onSchemaChange回调,当组合后的Schema完成更新时会自动触发,可在此回调中直接将Schema写入文件。
代码示例:
import { Module } from '@nestjs/common'; import { GraphQLGatewayModule, IntrospectAndCompose } from '@nestjs/graphql'; import { writeFileSync } from 'fs'; import { printSchema } from 'graphql'; @Module({ imports: [ GraphQLGatewayModule.forRootAsync({ useFactory: () => ({ server: { cors: true, // 根据项目需求配置网关服务参数 }, gateway: { supergraphSdl: new IntrospectAndCompose({ subgraphs: [ { name: 'users', url: 'http://localhost:3001/graphql' }, // 依次添加所有子图配置 ], onSchemaChange: ({ schema }) => { const schemaContent = printSchema(schema); writeFileSync('./schema.gql', schemaContent); console.log('组合Schema已保存到schema.gql'); }, }), }, }), }), ], }) export class AppModule {}
方案二:在onApplicationBootstrap中等待Schema就绪
onApplicationBootstrap钩子会在所有模块初始化完成后执行,此时可注入Gateway实例,手动等待Schema组合完成后再保存。
代码示例:
import { Injectable, OnApplicationBootstrap, Inject } from '@nestjs/common'; import { Gateway } from '@apollo/gateway'; import { writeFileSync } from 'fs'; import { printSchema } from 'graphql'; import { GATEWAY_INSTANCE } from '@nestjs/graphql'; @Injectable() export class SchemaSaver implements OnApplicationBootstrap { constructor(@Inject(GATEWAY_INSTANCE) private readonly gateway: Gateway) {} async onApplicationBootstrap() { // 等待Gateway完成子图 introspection 和Schema组合 await this.gateway.load(); final schema = await this.gateway.schema(); const schemaContent = printSchema(schema); writeFileSync('./schema.gql', schemaContent); console.log('组合Schema已成功保存'); } }
将SchemaSaver加入对应模块的providers数组即可生效。
方案三:编写独立脚本手动生成Schema
若不需要在应用启动时自动生成,可编写独立脚本,手动触发子图 introspection 并组合保存Schema:
import { IntrospectAndCompose } from '@apollo/gateway'; import { writeFileSync } from 'fs'; import { printSchema } from 'graphql'; async function generateSupergraphSchema() { const composer = new IntrospectAndCompose({ subgraphs: [ { name: 'users', url: 'http://localhost:3001/graphql' }, // 配置所有子图地址 ], }); const schema = await composer.getSchema(); const schemaContent = printSchema(schema); writeFileSync('./schema.gql', schemaContent); console.log('Supergraph Schema已生成'); } generateSupergraphSchema().catch(err => console.error('生成失败:', err));
运行脚本前需确保所有子图服务处于启动状态。
注意事项
- 所有子图服务必须在Gateway启动或脚本运行时保持可用,否则introspection流程会失败。
- 方案一可自动监听子图Schema更新并重新保存,方案二需重启应用才能更新保存的Schema,方案三需重新运行脚本。
- 可根据项目结构调整Schema保存路径,比如
../client/schema.gql,方便客户端代码生成工具直接读取。
内容的提问来源于stack exchange,提问作者cbolles
相关产品推荐
相关产品推荐

