快速开始
利用TypeScript和GraphQL的强大功能
GraphQL是一种强大的API查询语言和运行时,用于使用现有数据执行这些查询。它是一种优雅的方法,解决了REST API通常遇到的许多问题。作为背景,我们建议阅读GraphQL和REST之间的比较。GraphQL与TypeScript结合使用,可以帮助您在GraphQL查询中开发更好的类型安全性,为您提供端到端的类型支持。
在本章中,我们假设您对GraphQL有基本的了解,并专注于如何使用内置的@nestjs/graphql模块。GraphQLModule可以配置为使用Apollo服务器(使用@nestjs/apollo驱动程序)和Mercurius(使用@nestjs/mercurius)。我们为这些经过验证的GraphQL包提供官方集成,以提供在Nest中使用GraphQL的简单方法(查看更多集成这里)。
您也可以构建自己的专用驱动程序(在这里了解更多)。
安装
首先安装所需的包:
# 对于Express和Apollo(默认)
$ npm i @nestjs/graphql @nestjs/apollo @apollo/server@^4.12.2 graphql
# 对于Fastify和Apollo
# npm i @nestjs/graphql @nestjs/apollo @apollo/server@^4.12.2 @as-integrations/fastify graphql
# 对于Fastify和Mercurius
# npm i @nestjs/graphql @nestjs/mercurius graphql mercurius
警告 @nestjs/graphql@>=9和@nestjs/apollo^10包与Apollo v3兼容(查看Apollo Server 3迁移指南了解更多详情),而@nestjs/graphql@^8仅支持Apollo v2(例如,apollo-server-express@2.x.x包)。
概述
Nest提供了两种构建GraphQL应用程序的方法:代码优先和模式优先方法。您应该选择最适合您的方法。本GraphQL部分的大多数章节分为两个主要部分:如果您采用代码优先方法,您应该遵循的一个部分,以及如果您采用模式优先方法要使用的另一个部分。
在代码优先方法中,您使用装饰器和TypeScript类来生成相应的GraphQL模式。如果您更喜欢专门使用TypeScript并避免在语言语法之间进行上下文切换,这种方法很有用。
在模式优先方法中,真实来源是GraphQL SDL(模式定义语言)文件。SDL是一种与语言无关的方式,可以在不同平台之间共享模式文件。Nest会根据GraphQL模式自动生成您的TypeScript定义(使用类或接口),以减少编写冗余样板代码的需要。
GraphQL和TypeScript入门
提示 在接下来的章节中,我们将集成@nestjs/apollo包。如果您想使用mercurius包,请导航到此部分。
安装包后,我们可以导入GraphQLModule并使用forRoot()静态方法对其进行配置。
@@filename()
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
}),
],
})
export class AppModule {}
提示 对于mercurius集成,您应该使用MercuriusDriver和MercuriusDriverConfig。两者都从@nestjs/mercurius包中导出。
forRoot()方法接受一个选项对象作为参数。这些选项被传递给底层驱动程序实例(在这里阅读更多可用设置:Apollo和Mercurius)。例如,如果您想禁用playground并关闭debug模式(对于Apollo),请传递以下选项:
@@filename()
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
playground: false,
}),
],
})
export class AppModule {}
在这种情况下,这些选项将被转发到ApolloServer构造函数。
GraphQL playground
playground是一个图形化、交互式、浏览器内的GraphQL IDE,默认情况下在与GraphQL服务器本身相同的URL上可用。要访问playground,您需要配置并运行一个基本的GraphQL服务器。要立即查看它,您可以安装并构建这里的工作示例。或者,如果您正在跟随这些代码示例,一旦您完成了解析器章节中的步骤,您就可以访问playground。
有了这些,并且您的应用程序在后台运行,您可以打开Web浏览器并导航到http://localhost:3000/graphql(主机和端口可能因您的配置而异)。然后您将看到GraphQL playground,如下所示。

注意 @nestjs/mercurius集成不附带内置的GraphQL Playground集成。相反,您可以使用GraphiQL(设置graphiql: true)。
警告 更新(2025年4月14日):默认的Apollo playground已被弃用,将在下一个主要版本中删除。相反,您可以使用GraphiQL,只需在GraphQLModule配置中设置graphiql: true,如下所示:
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
graphiql: true,
}),
如果您的应用程序使用订阅,请确保使用graphql-ws,因为GraphiQL不支持subscriptions-transport-ws。
代码优先
在代码优先方法中,您使用装饰器和TypeScript类来生成相应的GraphQL模式。
要使用代码优先方法,首先将autoSchemaFile属性添加到选项对象:
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
}),
autoSchemaFile属性值是您自动生成的模式将被创建的路径。或者,可以在内存中动态生成模式。要启用此功能,请将autoSchemaFile属性设置为true:
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: true,
}),
默认情况下,生成的模式中的类型将按照它们在包含的模块中定义的顺序排列。要按字典顺序对模式进行排序,请将sortSchema属性设置为true:
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
sortSchema: true,
}),
示例
完整的代码优先示例可在这里获得。
模式优先
要使用模式优先方法,首先将typePaths属性添加到选项对象。typePaths属性指示GraphQLModule应该在哪里查找您将编写的GraphQL SDL模式定义文件。这些文件将在内存中合并;这允许您将模式拆分为多个文件并将它们放置在解析器附近。
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
typePaths: ['./**/*.graphql'],
}),
您通常还需要具有与GraphQL SDL类型对应的TypeScript定义(类和接口)。手动创建相应的TypeScript定义是冗余和繁琐的。它使我们没有单一的真实来源——在SDL中进行的每次更改都迫使我们也调整TypeScript定义。为了解决这个问题,@nestjs/graphql包可以从抽象语法树(AST)自动生成TypeScript定义。要启用此功能,请在配置GraphQLModule时添加definitions选项属性。
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
typePaths: ['./**/*.graphql'],
definitions: {
path: join(process.cwd(), 'src/graphql.ts'),
},
}),
definitions对象的path属性指示保存生成的TypeScript输出的位置。默认情况下,所有生成的TypeScript类型都创建为接口。要生成类,请使用值为'class'的outputAs属性。
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
typePaths: ['./**/*.graphql'],
definitions: {
path: join(process.cwd(), 'src/graphql.ts'),
outputAs: 'class',
},
}),
上述方法在每次应用程序启动时动态生成TypeScript定义。或者,构建一个简单的脚本来按需生成这些可能更可取。例如,假设我们创建以下脚本作为generate-typings.ts:
import { GraphQLDefinitionsFactory } from '@nestjs/graphql';
import { join } from 'path';
const definitionsFactory = new GraphQLDefinitionsFactory();
definitionsFactory.generate({
typePaths: ['./src/**/*.graphql'],
path: join(process.cwd(), 'src/graphql.ts'),
outputAs: 'class',
});
现在您可以按需运行此脚本:
$ ts-node generate-typings
提示 您可以预先编译脚本(例如,使用tsc)并使用node执行它。
要为脚本启用监视模式(在任何.graphql文件更改时自动生成类型),请将watch选项传递给generate()方法。
definitionsFactory.generate({
typePaths: ['./src/**/*.graphql'],
path: join(process.cwd(), 'src/graphql.ts'),
outputAs: 'class',
watch: true,
});
要为每个对象类型自动生成额外的__typename字段,请启用emitTypenameField选项:
definitionsFactory.generate({
// ...
emitTypenameField: true,
});
要将解析器(查询、变更、订阅)生成为没有参数的普通字段,请启用skipResolverArgs选项:
definitionsFactory.generate({
// ...
skipResolverArgs: true,
});
要将枚举生成为TypeScript联合类型而不是常规TypeScript枚举,请将enumsAsTypes选项设置为true:
definitionsFactory.generate({
// ...
enumsAsTypes: true,
});
Apollo Sandbox
要使用Apollo Sandbox而不是graphql-playground作为本地开发的GraphQL IDE,请使用以下配置:
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
playground: false,
plugins: [ApolloServerPluginLandingPageLocalDefault()],
}),
],
})
export class AppModule {}
示例
完整的模式优先示例可在这里获得。
访问生成的模式
在某些情况下(例如端到端测试),您可能希望获得对生成的模式对象的引用。在端到端测试中,您可以使用graphql对象运行查询,而无需使用任何HTTP监听器。
您可以使用GraphQLSchemaHost类访问生成的模式(在代码优先或模式优先方法中):
const { schema } = app.get(GraphQLSchemaHost);
提示 您必须在应用程序初始化后(在onModuleInit钩子被app.listen()或app.init()方法触发后)调用GraphQLSchemaHost#schema getter。
异步配置
当您需要异步而不是静态地传递模块选项时,请使用forRootAsync()方法。与大多数动态模块一样,Nest提供了几种处理异步配置的技术。
一种技术是使用工厂函数:
GraphQLModule.forRootAsync<ApolloDriverConfig>({
driver: ApolloDriver,
useFactory: () => ({
typePaths: ['./**/*.graphql'],
}),
}),
像其他工厂提供者一样,我们的工厂函数可以是异步的并且可以通过inject注入依赖项。
GraphQLModule.forRootAsync<ApolloDriverConfig>({
driver: ApolloDriver,
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
typePaths: configService.get<string>('GRAPHQL_TYPE_PATHS'),
}),
inject: [ConfigService],
}),
或者,您可以使用类而不是工厂来配置GraphQLModule,如下所示:
GraphQLModule.forRootAsync<ApolloDriverConfig>({
driver: ApolloDriver,
useClass: GqlConfigService,
}),
上述构造在GraphQLModule内实例化GqlConfigService,使用它来创建选项对象。请注意,在此示例中,GqlConfigService必须实现GqlOptionsFactory接口,如下所示。GraphQLModule将在提供的类的实例化对象上调用createGqlOptions()方法。
@Injectable()
class GqlConfigService implements GqlOptionsFactory {
createGqlOptions(): ApolloDriverConfig {
return {
typePaths: ['./**/*.graphql'],
};
}
}
如果您想重用现有的选项提供者而不是在GraphQLModule内创建私有副本,请使用useExisting语法。
GraphQLModule.forRootAsync<ApolloDriverConfig>({
imports: [ConfigModule],
useExisting: ConfigService,
}),
Mercurius集成
Fastify用户(在这里阅读更多)可以使用@nestjs/mercurius驱动程序,而不是使用Apollo。
@@filename()
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { MercuriusDriver, MercuriusDriverConfig } from '@nestjs/mercurius';
@Module({
imports: [
GraphQLModule.forRoot<MercuriusDriverConfig>({
driver: MercuriusDriver,
graphiql: true,
}),
],
})
export class AppModule {}
提示 应用程序运行后,打开浏览器并导航到http://localhost:3000/graphiql。您应该看到GraphQL IDE。
forRoot()方法接受一个选项对象作为参数。这些选项被传递给底层驱动程序实例。在这里阅读更多可用设置。
多个端点
@nestjs/graphql模块的另一个有用功能是能够同时服务多个端点。这让您可以决定哪些模块应该包含在哪个端点中。默认情况下,GraphQL在整个应用程序中搜索解析器。要将此扫描限制为仅模块的子集,请使用include属性。
GraphQLModule.forRoot({
include: [CatsModule],
}),
警告 如果您在单个应用程序中使用带有@as-integrations/fastify包的@apollo/server与多个GraphQL端点,请确保在GraphQLModule配置中启用disableHealthCheck设置。
第三方集成
示例
工作示例可在这里获得。