GraphQL + Nest.js 微服务开发
约 821 字大约 3 分钟
GraphQLNest.js微服务TypeScript
2026-04-08
Nest.js 提供了 @nestjs/graphql 模块,基于 Apollo Server 并深度融合依赖注入、装饰器和 Code First 开发体验。本文围绕一个简单的微服务场景,介绍完整搭建流程。
1. 安装依赖
pnpm add @nestjs/graphql @nestjs/apollo @apollo/server graphql2. 模块定义:Code First 模式
Nest 支持两种风格:
- Schema First:先写
.graphql文件,再生成 TypeScript - Code First(推荐):用 TypeScript 装饰器定义类型,自动生成 Schema
在 AppModule 中注册:
import { Module } from '@nestjs/common'
import { GraphQLModule } from '@nestjs/graphql'
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'
import { join } from 'node:path'
import { UserModule } from './user/user.module'
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
sortSchema: true,
playground: false,
context: ({ req }) => ({ req }),
}),
UserModule,
],
})
export class AppModule {}autoSchemaFile 会根据代码里的装饰器自动生成 .gql 文件,便于 CI 校验或前端代码生成。
3. 定义 Object Type
src/user/user.model.ts:
import { Field, ID, ObjectType } from '@nestjs/graphql'
@ObjectType()
export class User {
@Field(() => ID)
id: string
@Field()
name: string
@Field({ nullable: true })
email?: string
}4. 定义 Input Type
src/user/dto/create-user.input.ts:
import { Field, InputType } from '@nestjs/graphql'
import { IsEmail, IsNotEmpty } from 'class-validator'
@InputType()
export class CreateUserInput {
@Field()
@IsNotEmpty()
name: string
@Field({ nullable: true })
@IsEmail()
email?: string
}5. 编写 Resolver
src/user/user.resolver.ts:
import { Args, ID, Mutation, Query, Resolver } from '@nestjs/graphql'
import { User } from './user.model'
import { UserService } from './user.service'
import { CreateUserInput } from './dto/create-user.input'
@Resolver(() => User)
export class UserResolver {
constructor(private readonly userService: UserService) {}
@Query(() => [User])
users() {
return this.userService.findAll()
}
@Query(() => User, { nullable: true })
user(@Args('id', { type: () => ID }) id: string) {
return this.userService.findById(id)
}
@Mutation(() => User)
createUser(@Args('input') input: CreateUserInput) {
return this.userService.create(input)
}
}6. Service 与模块装配
src/user/user.service.ts:
import { Injectable } from '@nestjs/common'
import { User } from './user.model'
import { CreateUserInput } from './dto/create-user.input'
@Injectable()
export class UserService {
private users: User[] = []
findAll() {
return this.users
}
findById(id: string) {
return this.users.find((u) => u.id === id)
}
create(input: CreateUserInput) {
const user: User = { id: String(this.users.length + 1), ...input }
this.users.push(user)
return user
}
}src/user/user.module.ts:
import { Module } from '@nestjs/common'
import { UserResolver } from './user.resolver'
import { UserService } from './user.service'
@Module({
providers: [UserResolver, UserService],
})
export class UserModule {}7. 鉴权 Guard
Nest 的 Guard 同样适用于 GraphQL,需要用 GqlExecutionContext 取出上下文:
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'
import { GqlExecutionContext } from '@nestjs/graphql'
@Injectable()
export class GqlAuthGuard implements CanActivate {
canActivate(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context)
const req = ctx.getContext().req
return Boolean(req.headers.authorization)
}
}在 resolver 方法上使用 @UseGuards(GqlAuthGuard) 即可。
8. 微服务架构中的 GraphQL
GraphQL 在微服务体系中有几种常见模式:
8.1 网关聚合(BFF)
前端只跟一个 GraphQL 网关通信,网关内部通过 HTTP / gRPC / 消息队列调用下游微服务:
Client ──> GraphQL Gateway ──> UserService (HTTP)
├─> OrderService (gRPC)
└─> NotifyService (MQ)在 Nest 中可通过 @nestjs/microservices 让网关通过 ClientProxy 调用下游:
@Injectable()
export class OrderGqlService {
constructor(@Inject('ORDER_SERVICE') private client: ClientProxy) {}
getOrders(userId: string) {
return this.client.send({ cmd: 'get_orders' }, { userId })
}
}8.2 Apollo Federation
多个子服务各自暴露 GraphQL Schema,通过 Apollo Gateway 合并为一个统一 Schema,每个子服务用 @key 声明实体:
@ObjectType()
@Directive('@key(fields: "id")')
export class User {
@Field(() => ID) id: string
@Field() name: string
}Nest.js 通过 ApolloFederationDriver 支持此模式:
GraphQLModule.forRoot<ApolloFederationDriverConfig>({
driver: ApolloFederationDriver,
autoSchemaFile: { federation: 2 },
})相比网关聚合,Federation 让每个团队独立演进自己的 Schema,更适合规模化组织。
9. 项目构建与部署
- 开发:
nest start --watch - 构建:
nest build,产物在dist/ - Schema 校验:CI 中 diff 自动生成的
schema.gql,避免破坏性变更 - 监控:Apollo Studio、OpenTelemetry GraphQL 插件可对 resolver 级别追踪耗时
10. 小结
Nest.js + GraphQL 的组合优势在于:
- 类型安全:TypeScript → Schema → 前端类型全链路贯通
- 依赖注入:Service、Guard、Interceptor 与 REST 端共享
- 生态完整:无缝接入 TypeORM、Prisma、微服务传输层
- 渐进式:可以先在现有 REST 项目中新增一个
/graphql端点,逐步迁移
