使

使用 NestJS 搭建 Node.js 服务器,包含 TypeScript 和 GraphQL

2025-06-08

使用 NestJS 搭建 Node.js 服务器,包含 TypeScript 和 GraphQL

最近,我发现了 NestJS,并立刻爱上了它。它在一个 Node 框架中整合了我喜欢的 Angular 的所有特性(包括 TypeScript、自定的文件结构、模块、装饰器和依赖注入)。此外,它还支持 GraphQL。

开始之前

本教程不适合初学者。它不会涵盖 Node 基础知识。如果您想了解 Node 和 Express 的工作原理,我制作了一系列视频,其中我创建并部署了一个基本的时间戳微服务。此外,本教程不会涵盖 GraphQL 基础知识。

根据这篇博文制作了一个视频教程。建议大家阅读这篇博文并观看视频,因为它们可以互相补充。

本教程使用的是nest-cli6.6.4 版本,编写于 2019 年 9 月 18 日。如果有任何内容过时或需要报告任何错误/障碍,请随时给我发推文

如果您在任何时候感到迷茫,您可以查看此代码的最终形式

GitHub 徽标 AryanJ-NYC / nestjs-graphql-tutorial

请参阅下面的自述文件

解决了所有这些问题之后,我们就开始吧!

NestJS 入门

NestJS 是一个兼容 TypeScript 和纯 JavaScript 的 Node.js 框架。它开箱即用地支持guardpipe拦截器。这使得它易于使用且功能强大。

首先,安装 NestJS CLI。这样您就可以轻松创建一个新的 NestJS 项目。

npm i -g @nestjs/cli
nest new my-node-project
Enter fullscreen mode Exit fullscreen mode

其中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
Enter fullscreen mode Exit fullscreen mode

现在进入该目录并运行新创建的 Node 服务器:

cd my-node-project
npm run start:dev
Enter fullscreen mode Exit fullscreen mode

转到http://localhost:3000(默认)以访问“Hello World!”端点。

融入 GraphQL

GraphQL是一种 API 查询语言。NestJS 使用他们自己的GraphQLModule(从 导入的)GraphQL 语言,它是Apollo@nestj/graphql GraphQL 服务器的包装器

在开始之前,让我们先删除即将不再使用的文件(用于“Hello World!”端点的文件)。更具体地说,请删除src/app.controller.tssrc/app.service.ts以及它们对应的测试文件。

要开始使用 GraphQL 和 NestJS,请安装必要的依赖项:

npm i --save @nestjs/graphql apollo-server-express graphql-tools graphql
Enter fullscreen mode Exit fullscreen mode

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 {}
Enter fullscreen mode Exit fullscreen mode

我知道,我知道。我把这里面的很多变化都告诉了大家。NestJS GraphQL 文档对这些变化的解释非常到位。以下是我的看法。

GraphQLModule.forRoot()

GraphQLModule这将向服务器注册。该.forRoot()方法以一个options对象作为参数。

定义

@nestjs/graphql包会自动根据 GraphQL 模式生成 TypeScript 定义(参见typePaths)。我们使用definitions对象来配置pathTypeScript 定义的保存位置。默认情况下,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!
}
Enter fullscreen mode Exit fullscreen mode

重启 Node 服务器,访问http://localhost:3000/graphql,你会看到一个 GraphQL 游乐场。当然,由于我们还没有编写解析器,你尝试运行的任何查询或修改都会报错。

使用 NestJS 编写 GraphQL 解析器

让我们编写第一个 GraphQL 解析器。首先,创建一个新的 NestJS 模块:

nest generate module messages
Enter fullscreen mode Exit fullscreen mode

这将导入MessagesModuleAppModule创建一个新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;
  }
}
Enter fullscreen mode Exit fullscreen mode

注意 NestJS 为我们提供的装饰器(ResolverQuery)。它们会自动映射到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 {}
Enter fullscreen mode Exit fullscreen mode

转到http://localhost:3000/graphql,刷新页面,然后运行消息查询:

{
  messages {
    description
  }
}
Enter fullscreen mode Exit fullscreen mode

如果一切操作正确,您应该会看到种子消息:
GraphQL 游乐场,包含消息查询和返回的消息数组(包含种子消息)

现在让我们将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;
  }
}
Enter fullscreen mode Exit fullscreen mode

将变异添加到解析器后,让我们返回到http://localhost:3000/graphql 的GraphQL Playground并创建一些消息:

mutation {
  createMessage(description: "This is a witty description") {
    description
  }
}
Enter fullscreen mode Exit fullscreen mode

应该成功返回:

带有消息变异和返回消息的 GraphQL 游乐场

请随意使用我们的新变异来创建一些消息并查询所有消息。

结论

这样,您现在就拥有了一个包含 GraphQL 的 NestJS 服务器、一个简单的 GraphQL 模式以及一个针对该模式的简单解析器(包含查询和修改功能)。如果您正确完成了所有操作,messages查询和修改应该可以像在本演示服务器createMessage中一样正常工作。再次强调,如果您在任何时候遇到困难并想查看整个演示项目,请查看我的 GitHub 仓库

下一步是向此堆栈添加数据库。Prisma是一个很棒的解决方案,它为我们提供了额外的 GraphQL 和数据库工具。在本系列的下一篇文章中,我们将深入探讨如何使用Prisma保存消息。

如果您喜欢这篇文章,请在TwitterYouTubeGitHub上关注我以支持我

鏂囩珷鏉ユ簮锛�https://dev.to/aryanjnyc/stand-up-a-node-js-server-with-nestjs-include-typescript-and-graphql-fao
PREV
使用 Go 在单个二进制文件中提供单页应用程序
NEXT
我从 Apollo Client 迁移到了 Vercel SWR 和 Prisma graphql-request...你也可以!