Skip to content

Nest中使用GraphQL

环境信息:@nestjs/graphql 12.x、@nestjs/apollo 12.x、@apollo/server 4.x

新建个项目

nest new nest-graphql -g -p pnpm

安装 graphqlapollo 相关的包

pnpm add @nestjs/graphql@12 @nestjs/apollo@12 @apollo/server graphql

@nestjs/graphql@nestjs/apollo现在使用12的版本,因为和nest cli直接生成的@nestjs/core@nestjs/common版本还不兼容

首先,在 app.module.ts中引入 GraphQLModule

import { Module } from '@nestjs/common'
import { AppController } from './app.controller'
import { AppService } from './app.service'
import { ApolloDriver } from '@nestjs/apollo'
import { GraphQLModule } from '@nestjs/graphql'
import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default'
@Module({
imports: [
GraphQLModule.forRoot({
driver: ApolloDriver,
typePaths: ['./**/*.graphql'],
playground: false,
plugins: [ApolloServerPluginLandingPageLocalDefault()],
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

其中:

driver:指定驱动

typePaths:指定schema位置,也就是后缀为.graphql的文件

playground: false,plugins: [ApolloServerPluginLandingPageLocalDefault()]这两个完全是为了能够有上节课一样的playground模版,用起来简单方便

为了能在VSCode中,实现相关语法高亮,我们可以下载插件

image-20250305194201463

我们可以在src下创建schema文件,命名为schema.graphql,然后直接把上节课的类型定义直接复制粘贴进去

type Employee {
id: String
name: String
sex: String
age: Int
}
type Department {
id: String
name: String
employees: [Employee]
}
type Query {
employees: [Employee]
departments: [Department]
employeesByDepartmentName(name: String!): [Employee]
}
type Res {
success: Boolean
id: String
}
type Mutation {
addEmployee(name: String!, age: Int!, sex: String!): Res
updateEmployee(id: String!, name: String!, age: Int!, sex: String!): Res
deleteEmployee(id: String!): Res
}

我们可以通过命令行直接创建resolver

image-20250305195845778

我们直接通过命令创建Employee相关的resolver

nest g resolver employee --no-spec

当然,通过命令行创建之后,直接就加入到了app.module.ts中了

@Module({
......
controllers: [AppController],
providers: [AppService, EmployeeResolver],
})
export class AppModule {}

和上节课一样,实现QueryMutation对应的逻辑,现在我们可以通过相应的装饰器来实现

import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'
let employees = [
{
id: '1',
name: async () => {
await '取数据'
return 'jack'
},
sex: '',
age: 18,
},
{
id: '2',
name: 'rose',
sex: '',
age: 20,
},
{
id: '3',
name: 'tom',
sex: '',
age: 31,
},
]
const departments = [
{
id: '1',
name: '技术部',
employees: employees,
},
]
@Resolver()
export class EmployeeResolver {
@Query('employees')
async getEmployees() {
return employees
}
@Query('departments')
async getDepartments() {
return departments
}
@Mutation('addEmployee')
async addEmployee(
@Args('name') name: string,
@Args('age') age: number,
@Args('sex') sex: string
) {
employees.push({
id: Math.ceil(Math.random() * 100) + '',
name,
age,
sex,
})
return {
success: true,
id: Math.ceil(Math.random() * 100) + '',
}
}
@Mutation('updateEmployee')
async updateEmployee(
@Args('id') id: string,
@Args('name') name: string,
@Args('age') age: number,
@Args('sex') sex: string
) {
employees.forEach((item) => {
if (item.id === id) {
item.name = name
item.age = age
item.sex = sex
}
})
return {
success: true,
id,
}
}
@Mutation('deleteEmployee')
async deleteEmployee(@Args('id') id: string) {
employees = employees.filter((item) => item.id !== id)
return {
success: true,
id: id,
}
}
}

接下来,我们只需要启动程序pnpm run start:dev,通过对应的路由,就能访问

image-20250305204208513

我们直接在后端开启跨域支持

async function bootstrap() {
const app = await NestFactory.create(AppModule)
app.enableCors()
await app.listen(process.env.PORT ?? 3000)
}

这样,我们开启之前的前端项目,只需要修改一下url地址,就可以直接访问到了。

const client = new ApolloClient({
uri: 'http://localhost:3000/graphql',
cache: new InMemoryCache(),
})