使用 NestJS 搭建 Node.js 服务器,包含 TypeScript 和 GraphQL
最近,我发现了 NestJS,并立刻爱上了它。它在一个 Node 框架中整合了我喜欢的 Angular 的所有特性(包括 TypeScript、自定的文件结构、模块、装饰器和依赖注入)。此外,它还支持 GraphQL。
开始之前
本教程不适合初学者。它不会涵盖 Node 基础知识。如果您想了解 Node 和 Express 的工作原理,我制作了一系列视频,其中我创建并部署了一个基本的时间戳微服务。此外,本教程不会涵盖 GraphQL 基础知识。
我根据这篇博文制作了一个视频教程。建议大家阅读这篇博文并观看视频,因为它们可以互相补充。
本教程使用的是nest-cli
6.6.4 版本,编写于 2019 年 9 月 18 日。如果有任何内容过时或需要报告任何错误/障碍,请随时给我发推文。
如果您在任何时候感到迷茫,您可以查看此代码的最终形式。
AryanJ-NYC / nestjs-graphql-tutorial
请参阅下面的自述文件
解决了所有这些问题之后,我们就开始吧!
NestJS 入门
NestJS 是一个兼容 TypeScript 和纯 JavaScript 的 Node.js 框架。它开箱即用地支持guard、pipe和拦截器。这使得它易于使用且功能强大。
首先,安装 NestJS CLI。这样您就可以轻松创建一个新的 NestJS 项目。
npm i -g @nestjs/cli
nest new my-node-project
其中my-node-project
是您的 Node 项目名称。如果您已安装 NPM 和 Yarn,NestJS 会询问您的首选项。如果项目创建正确,您应该会得到一个具有以下结构的新项目:
.
├── README.md
├── nest-cli.json
├── package.json
├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── main.ts
├── test
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── tsconfig.build.json
├── tsconfig.json
├── tslint.json
└── yarn.lock
现在进入该目录并运行新创建的 Node 服务器:
cd my-node-project
npm run start:dev
转到http://localhost:3000(默认)以访问“Hello World!”端点。
融入 GraphQL
GraphQL是一种 API 查询语言。NestJS 使用他们自己的GraphQLModule
(从 导入的)GraphQL 语言,它是Apollo@nestj/graphql
GraphQL 服务器的包装器。
在开始之前,让我们先删除即将不再使用的文件(用于“Hello World!”端点的文件)。更具体地说,请删除src/app.controller.ts
、src/app.service.ts
以及它们对应的测试文件。
要开始使用 GraphQL 和 NestJS,请安装必要的依赖项:
npm i --save @nestjs/graphql apollo-server-express graphql-tools graphql
GraphQLModule
安装这些软件包后,在中注册/src/app.module.ts
:
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { join } from 'path';
@Module({
imports: [
GraphQLModule.forRoot({
definitions: {
path: join(process.cwd(), '/src/graphql.schema.d.ts'),
outputAs: 'class',
},
typePaths: ['./**/*.graphql'],
resolverValidationOptions: {
requireResolversForResolveType: false,
},
}),
],
})
export class AppModule {}
我知道,我知道。我把这里面的很多变化都告诉了大家。NestJS GraphQL 文档对这些变化的解释非常到位。以下是我的看法。
GraphQLModule.forRoot()
GraphQLModule
这将向服务器注册。该.forRoot()
方法以一个options
对象作为参数。
定义
该@nestjs/graphql
包会自动根据 GraphQL 模式生成 TypeScript 定义(参见typePaths
)。我们使用definitions
对象来配置path
TypeScript 定义的保存位置。默认情况下,GraphQL 类型会转换为接口。我个人更喜欢类,也就是 中显示的样子definitions.outputAs
。
类型路径
typePaths
告诉GraphQLModule
在项目中的哪里寻找 GraphQL 文件。
解析器验证选项
在不将 equals 设置为 false 的情况下运行服务器时,我收到类似这样resolverValidationOptions.requireResolversForResolveType
的警告。因此,它目前为 false。
好了,回到 GraphQL。src/schema.graphql
按如下方式添加到你的项目中:
type Message {
id: Int!
description: String!
}
type Query {
messages: [Message]!
}
type Mutation {
createMessage(description: String!): Message!
}
重启 Node 服务器,访问http://localhost:3000/graphql,你会看到一个 GraphQL 游乐场。当然,由于我们还没有编写解析器,你尝试运行的任何查询或修改都会报错。
使用 NestJS 编写 GraphQL 解析器
让我们编写第一个 GraphQL 解析器。首先,创建一个新的 NestJS 模块:
nest generate module messages
这将导入MessagesModule
并AppModule
创建一个新src/messages
目录,您的消息解析器的业务逻辑将存储在该目录中(明白我所说的 NestJS 模块化了吗?)。
现在,让我们创建该解析器。我们将创建一个名为 的虚拟变量messagesThatReallyShouldBeInADb
,它将作为我们的数据库,存储所有消息以及返回所有消息的 GraphQL 查询。在src/messages/messages.resolver.ts
:
import { Resolver, Query } from '@nestjs/graphql';
@Resolver()
export class MessagesResolver {
// this is just for demonstration purposes
// do NOT do this in real-life
// this is meant as a substitute for a database
messagesThatReallyShouldBeInADb = [
{ id: 0, description: 'The seed message' },
];
@Query()
messages() {
return this.messagesThatReallyShouldBeInADb;
}
}
注意 NestJS 为我们提供的装饰器(Resolver
和Query
)。它们会自动映射到messages
我们在中声明的查询src/schema.graphql
。现在我们必须将此解析器提供给MessagesModule
。在src/messages.module.ts
:
import { Module } from '@nestjs/common';
import { MessagesResolver } from './messages.resolver';
@Module({
providers: [MessagesResolver],
exports: [MessagesResolver],
})
export class MessagesModule {}
转到http://localhost:3000/graphql,刷新页面,然后运行消息查询:
{
messages {
description
}
}
现在让我们将createMessage
突变添加到src/messages/messages.resolver.ts
。记住,解析器类型签名需要四个参数(parent, args, context, info)
。NestJS 为每个参数提供了装饰器。对于这个特定的突变,我们使用@Args()
装饰器并将要访问的参数名称传递给它(description
):
import { Mutation, Resolver, Query, Args } from '@nestjs/graphql';
@Resolver()
export class MessagesResolver {
// this is just for demonstration purposes
// do NOT do this in real-life
// this is meant as a substitute for a databse
messagesThatReallyShouldBeInADb = [
{ id: 0, description: 'The seed message' },
];
@Query()
messages() {
return this.messagesThatReallyShouldBeInADb;
}
@Mutation()
createMessage(@Args('description') description: string) {
const id = this.messagesThatReallyShouldBeInADb.length;
const newMessage = { id, description };
this.messagesThatReallyShouldBeInADb.push(newMessage);
return newMessage;
}
}
将变异添加到解析器后,让我们返回到http://localhost:3000/graphql 的GraphQL Playground并创建一些消息:
mutation {
createMessage(description: "This is a witty description") {
description
}
}
应该成功返回:
请随意使用我们的新变异来创建一些消息并查询所有消息。
结论
这样,您现在就拥有了一个包含 GraphQL 的 NestJS 服务器、一个简单的 GraphQL 模式以及一个针对该模式的简单解析器(包含查询和修改功能)。如果您正确完成了所有操作,messages
查询和修改应该可以像在本演示服务器createMessage
中一样正常工作。再次强调,如果您在任何时候遇到困难并想查看整个演示项目,请查看我的 GitHub 仓库。
下一步是向此堆栈添加数据库。Prisma是一个很棒的解决方案,它为我们提供了额外的 GraphQL 和数据库工具。在本系列的下一篇文章中,我们将深入探讨如何使用Prisma保存消息。
如果您喜欢这篇文章,请在Twitter、YouTube和GitHub上关注我以支持我。
鏂囩珷鏉ユ簮锛�https://dev.to/aryanjnyc/stand-up-a-node-js-server-with-nestjs-include-typescript-and-graphql-fao