如何在NestJS的Apollo.service.ts中启动Apollo Server v4联邦子图
解决NestJS中Apollo联邦API(Server v4)的三个常见问题
问题1:配置context时提示属性不存在于ApolloServerOptionsWithSchema类型
Apollo Server v4中,ApolloServerOptionsWithSchema类型仅针对预构建好Schema的场景,确实不包含顶层context属性。解决方式二选一:
- 改用
ApolloServerOptions类型,在选项中同时传入Schema和context:import { ApolloServer, ApolloServerOptions } from '@apollo/server'; import { buildSubgraphSchema } from '@apollo/subgraph'; const schema = buildSubgraphSchema({ typeDefs, resolvers }); const server = new ApolloServer<ApolloServerOptions>({ schema, context: async ({ req }) => { // 自定义上下文逻辑,比如从请求中提取用户信息 return { user: await extractUserFromRequest(req) }; }, }); - 若必须使用
ApolloServerOptionsWithSchema,可在构建Schema时绑定context:import { buildSubgraphSchema } from '@apollo/subgraph'; const schema = buildSubgraphSchema({ typeDefs, resolvers, context: async ({ req }) => { /* 上下文逻辑 */ }, });
问题2:ApolloServer实例无getMiddleware方法
Apollo Server v4已彻底移除getMiddleware方法,需根据集成方式选择替代方案:
如果要和NestJS的HTTP适配器集成,使用对应框架的中间件适配器:
import { expressMiddleware } from '@apollo/server/express4'; import { json } from 'body-parser'; import { NestExpressApplication } from '@nestjs/platform-express'; // 先启动Apollo Server await server.start(); // 将Apollo中间件挂载到NestJS的Express实例上 app.use('/graphql', json(), expressMiddleware(server, { context: async ({ req }) => ({ req }), }));
问题3:startStandaloneServer在NestJS main.ts中的集成方案(Server/Context定义在AuthModule内)
核心是将Apollo Server的初始化逻辑封装为AuthModule的提供者,再在main.ts中通过Nest容器获取并集成:
- 在AuthModule中定义Apollo Server提供者:
// auth.module.ts import { Module } from '@nestjs/common'; import { ApolloServer } from '@apollo/server'; import { buildSubgraphSchema } from '@apollo/subgraph'; @Module({ providers: [ { provide: 'APOLLO_AUTH_SERVER', useFactory: async () => { const schema = buildSubgraphSchema({ typeDefs: authTypeDefs, resolvers: authResolvers, }); const server = new ApolloServer({ schema, context: async ({ req }) => { /* 自定义上下文逻辑 */ }, }); await server.start(); return server; }, }, ], exports: ['APOLLO_AUTH_SERVER'], }) export class AuthModule {} - 在main.ts中获取并集成:
// main.ts import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { expressMiddleware } from '@apollo/server/express4'; import { json } from 'body-parser'; async function bootstrap() { const app = await NestFactory.create(AppModule); // 从Nest容器中获取AuthModule提供的Apollo Server实例 const authApolloServer = app.get('APOLLO_AUTH_SERVER'); // 方案1:挂载到Nest的HTTP服务上(推荐,统一端口和生命周期) app.use('/auth/graphql', json(), expressMiddleware(authApolloServer)); // 方案2:用startStandaloneServer启动独立服务(需指定不同端口) // await startStandaloneServer(authApolloServer, { // listen: { port: 4001 }, // }); await app.listen(3000); } bootstrap();
注意:startStandaloneServer会创建独立HTTP服务,需和Nest默认服务端口区分;优先选择和Nest HTTP服务集成的方式,保持生命周期一致。
内容的提问来源于stack exchange,提问作者MichaelE
相关产品推荐
相关产品推荐

