使用NestJS构建GraphQL API

作者 : IT 大叔 本文共6939个字,预计阅读时间需要18分钟 发布时间: 2020-09-16

我已经开发了十多年的Web应用程序。当Web围绕PHP建立时,我已经知道了美好的时光,这是该行业新手的兴起。在那些日子里,我对新框架及其功能的开发速度印象深刻。但是,大多数情况下,我对构建大型,可靠且真正重要的可伸缩应用程序和API的现有方法感到失望。框架不断出现。但是它们中的大多数都针对完全不同的原理,复制了现有类似物的态度。他们中的大多数人都制定了过于原始的责任规则,从根本上讲,这些规则允许人们以有时无法或什至不能被同事预测的方式和方式“表达”自己。我试图寻找一个框架,该框架在一个地方足够灵活,

当我决定切换到Node.js时,为了追求现代技术堆栈,性能原因,SPAa开发,更好的工具以与即时消息配合使用等,我在寻找可以代替旧框架的解决方案。可靠性和可扩展性,但将现代开发技术带入了我的生活。这就是我发现`NestJs`的方式,它基本上是`Express`上的更高抽象级别的框架,而后者又是基于Node.js构建的。

介绍

NestJs是Node.js框架中的后起之秀,它的模块化和可扩展性以及强大的体系结构使其越来越受欢迎。最初受到“ Angular”的启发,它在“ Typescript”的完全支持下结合了OOP(面向对象编程),FP(功能编程)和FRP(功能反应性编程)的元素。通过在后台使用“ Express”(或“ Fastify”),使其与大多数“ Express”中间件兼容。

为什么选择NestJs

优点

  1. Typescript是现代Web开发中的关键功能,如果可能的话,我们总是喜欢使用类型良好的代码库。
  • 使用装饰器观察,修改,验证或替换您的类,同时保留DRY原理并简洁明了。
  • 保持可预测性和易于理解。为您的应用程序设计完全类型化的业务逻辑,供您休息-~~ MasterCard ~~ SRP(单一职责原理)。
  • 如果您熟悉`Angular`,那么绝对应该喜欢`NestJs`。坚持众所周知的依赖注入原理,防护,拦截器,模块化结构等。

 

  • 其中的一个NestJs优点-模块化的方法,我们始终要保持我们的应用强大且可扩展。
    • 精心规划的模块化项目结构包括您要执行的大部分操作的最佳实践,它使您的同事可以预测哪种代码去哪儿,对于此类操作应使用哪种类,等等。
    • 与大多数流行的框架不同,在NestJ中,您不会遇到如何验证DTO的问题。由于结构周到,您的传入数据将由DTO进行键入,并按class-validator软件包使用Best NestJs最佳实践进行验证。
    • 您可以使用轻松扩展应用程序NestJs。Nest本身支持微服务架构开发风格。拥有广泛的文档和可用的不同方法。
    • 正如我在上一节中提到的那样,大多数必需的软件包已经通过“ @ nestjs / packagename”包装器与NestJs进行了集成,该包装器旨在使即使使用第三方库,项目结构仍可预测。
    • NestJs的发展非常迅速,已经通过了第七版并继续进行。高度的社区支持鼓励开发人员保持框架符合现代标准,目前已证明超过28.8k星。每次发布后,您始终可以找到更新,结构良好的综合文档,以及针对大多数应用的分步最佳实践设计流行案例。
    • 使用现代方法来构建由@@ nestjs / graphql包包装的GraphQL API。
    • 简单明了的请求生命周期使您更容易理解如何为请求的所有部分提供服务-验证,数据拦截,转换,响应部分等。
    • 用样式来支撑您的项目。使用方便的CLI启动新项目,生成模块,构建,安装或更新软件包库。
    </ol>
    

    缺点

    1. 由于单一责任原则(SRP),`NestJs`要求您清楚地了解哪个类应该对您要执行的操作负责,因此,在乞求时,花了一些时间才能根据文档识别/阅读您应该选择哪个类。用。
    2. 一些功能或集成是在某些库的基础上构建的,要遵循基本的责任模式,您应该习惯于这些库,接受它们的样式和方法。

    先决条件

    第1步-安装NestJs CLI

    要开始使用NestJ,您需要全局安装Nest CLI。这是一个用于构建新的NestJs应用程序的命令行工具。

    $ npm install -g @nestjs/cli
    

    这将使您可以访问用于安装项目的“嵌套”命令和其他特定于项目的命令。

    接下来,运行以下命令以在开发文件夹中搭建一个名为`todoapp-nest`的新项目:

    $ nest new todoapp-nest
    

    系统将询问您您要使用哪个程序包管理器,只需按照提示进行操作并做出相应的响应。接下来,安装完成后,将工作目录切换到新创建的项目中:

    $ cd todoapp-nest
    

    使用以下命令启动应用程序:

    npm run start
    

    您也可以运行以下命令以将Nodemon用于项目:

    // start the application using --watch option
    npm run start:dev
    

    在浏览器中导航到http:// localhost:3000,您将看到Hello World!消息,如下图所示:

    使用NestJS构建GraphQL API插图

    第2步-添加GraphQL

    GraphQL是API的查询语言,是用于使用现有数据来完成这些查询的运行时。它提供了API中数据的完整且易于理解的描述,为客户提供了更多的灵活性和针对开发人员需求的自定义工具。

    REST API是基于网络的软件的体系结构概念。另一方面,GraphQL是使用HTTP在单个端点上运行的查询语言,规范和一组工具。

    GraphQL的优势-您可以查询特别需要的数据,以维持安全性并提高性能。

    NestJs提供程序提供了两种构建GraphQL API的方法:

    我们更喜欢“代码优先”方法,因为我们允许使用装饰器和Typescript类来生成相应的“ GraphqQL”架构。这种方法的优势-我们可以避免在不同语言之间进行上下文切换,在编写模式时使用TS支持,受益于class-validator和class-transformer包,验证数据,使用GraphQL CLI生成模块,仅适用于“代码优先”方法。

    为了开始使用GraphQL,您需要安装软件包:

    $ npm i @nestjs/graphql graphql-tools graphql
    

    根据所使用的基础平台(“ Express”或“ Fastify”),还必须安装“ apollo-server-express”或“ apollo-server-fastify”。

    接下来,我们应该在app.module.ts中注册GraphQL模块:

    import { GraphQLModule } from '@nestjs/graphql';
    
    @Module({
      imports: [
        GraphQLModule.forRoot({
          autoSchemaFile: true,
        }),
        TasksModule
      ],
    ...
    

    要维护GraphQL提示,请在您的nest-cli.json中添加以下代码:

    {
      "collection": "@nestjs/schematics",
      "sourceRoot": "src",
      "compilerOptions": {
        "plugins": ["@nestjs/graphql/plugin"]
      }
    }
    

    安装软件包后,让我们创建任务模块。

    第3步-创建模块

    为了生成模块,我们需要运行以下命令:

    $ nest generate module tasks
    

    这将在src文件夹中创建一个名为task的新文件夹。在“书”文件夹中,您会找到一个task.module.ts文件:

    import { Module } from '@nestjs/common';
    @Module({})
    export class TasksModule {}
    

    这是由命令生成的,并且该模块也已添加到app.module.ts中,而这恰好是应用程序的根模块。

    接下来,我们必须创建解析器。

    第4步-创建解析器

    要生成解析器,请将其粘贴到命令提示符中:

    $ nest generate resolver tasks
    

    上面的命令将在“ tasks”文件夹中创建解析器“ tasks.resolver.ts”文件,并更新列出新提供程序的“ tasks.module.ts”。

    import { Resolver } from '@nestjs/graphql';
    
    @Resolver('Tasks')
    export class TasksResolver {}
    
    

    第5步-添加模型

    为了描述我们要使用的对象,我们应该为Task实例创建一个模型。为此,创建`models`文件夹并在其中添加`task.model.ts`,然后添加以下代码:

    import { Field, ID, ObjectType } from '@nestjs/graphql';
    
    @ObjectType()
    export class Task {
      @Field(() => ID)
      id: string;
    
      @Field()
      title: string;
    
      @Field()
      description: string;
    
      @Field()
      completed: boolean;
    }
    

    为简化起见,我们现在将不连接数据库,因此让我们为列表创建一个示例模拟数据。在`src`文件夹中创建`mocks`文件夹,然后使用以下代码添加名为`tasks.mock.ts`的文件:

    export const TASKS = [
      { id: '1', title: 'Task #1', description: "This is the description for the task #1", completed: false },
      { id: '2', title: 'Task #2', description: "This is the description for the task #2", completed: false },
      { id: '3', title: 'Task #3', description: "This is the description for the task #3", completed: true },
      { id: '4', title: 'Task #4', description: "This is the description for the task #4", completed: false },
      { id: '5', title: 'Task #5', description: "This is the description for the task #5", completed: true },
      { id: '6', title: 'Task #6', description: "This is the description for the task #6", completed: false },
      { id: '7', title: 'Task #7', description: "This is the description for the task #7", completed: false },
    ];
    

    接下来,我们应该创建一个服务来实现TodoApp的所有逻辑。

    步骤6-产生服务

    $ nest generate service tasks
    

    该命令将在./src/tasks文件夹中创建一个名为`tasks.service.ts`的新文件,并使用新的提供程序更新`tasks.module.ts`。

    首先,让我们导入模拟数据,以便我们可以为查询提供数据。

    import { Injectable } from '@nestjs/common';
    
    import { TASKS } from '../mocks/tasks.mock';
    
    @Injectable()
    export class TasksService {
      tasks = TASKS;
    }
    

    比我们应该添加两个方法,getTasks和getTask分别接收所有任务或某些任务。

    ...
    tasks = TASKS;
    
    getTasks() {
      return this.tasks;
    }
    
    getTask(id: number) {
      return this.tasks.find(task => task.id === id);
    }
    ...
    

    “ getTask”方法接受“ id”作为参数,其类型为“ number”,我们将在后续步骤中通过验证来确保此参数。

    现在是时候添加典型的mutation方法来创建Task实体了,我们将其命名为addTask:

    async addTask(input: AddTaskInput): Promise<Task[]> {
        const lastTask = this.tasks.slice(-1).pop();
        const task: Task = {
          id: lastTask.id + 1,
          title: input.title,
          description: input.description,
          completed: false,
        };
    
        this.tasks.push(task);
        return this.tasks;
      }
    

    您可以始终使用`async / await`语法进行异步操作,因为`NestJs`支持最新的`Typescript`。

    以相同的方式添加更新/删除方法:

      deleteTask(id: string): Task[] {
        const taskIndex = this.tasks.findIndex(item => item.id === id);
        if (taskIndex === -1) {
          throw new HttpException('Task not found', 404);
        }
    
        this.tasks.splice(taskIndex, 1);
        return this.tasks;
      }
    

    第7步-添加DTO

    DTO是一个数据传输对象,是一个TypeScript类,用于类型检查并定义创建Task时对象外观的结构。

    import { Field, InputType } from '@nestjs/graphql';
    import { IsNotEmpty } from 'class-validator';
    
    @InputType()
    export class AddTaskInput {
      @Field()
      @IsNotEmpty()
      title: string;
    
      @Field()
      description: string;
    }
    

    由于我们将为任务生成一个新的“ ID”,因此我们不想将其包含在其中

    步骤8-将服务注入解析器

    由于`NestJS`是围绕`Dependency Inject`概念构建的。我们可以通过将TasksService实例注入TasksResolver来提高性能。为此,我们需要将相应的代码添加到类构造函数中:

    import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
    import { TasksService } from './tasks.service';
    import { AddTaskInput } from './dto/add-task.input';
    import { UpdateTaskInput } from './dto/update-task.input';
    import { Task } from './models/tasks.model';
    
    @Resolver('Tasks')
    export class TasksResolver {
      constructor(
        private readonly taskService: TasksService
      ) {}
    
      @Query(type => [Task])
      async getTasks() {
        return this.taskService.getTasks();
      }
    
      @Query(type => Task)
      async getTask(
        @Args('id') id: string,
      ) {
        return this.taskService.getTask(id);
      }
    
      @Mutation(type => [Task])
      async addTask(
        @Args('input') input: AddTaskInput,
      ) {
        return this.taskService.addTask(input);
      }
    
      @Mutation(type => Task)
      async updateTask(
        @Args('input') input: UpdateTaskInput,
      ) {
        return this.taskService.updateTask(input);
      }
    
      @Mutation(type => [Task])
      async deleteTask(
        @Args('id') id: string,
      ) {
        return this.taskService.deleteTask(id);
      }
    }
    

    注意,`Query`装饰器应该从@@ nestjs / graphql`导入。

    接下来,我们通过构造函数注入TaskService并创建了一组Queries / Mutations。

    • getTasks()-返回所有任务;
    • getTask(id)-按ID返回任务;
    • addTask(input)-创建任务;
    • updateTask(input)-更新任务状态;
    • deleteTask(input)-删除任务;

    对于每个“查询/更改”,我们根据服务方法返回的数据为GraphQL设置返回类型。

    第9步-运行该应用程序!

    完成所有设置后,就该测试API了。为了进行测试,我们建议使用“ GraphQL Playground”(默认情况下可用)。

    默认情况下,服务器从“ 3000”端口启动。要打开“游乐场”,请访问“ http:// localhost:3000 / graphql”

    获取所有任务:
    使用NestJS构建GraphQL API插图(2)

    添加任务:
    使用NestJS构建GraphQL API插图(4)

    更新任务:
    使用NestJS构建GraphQL API插图(6)

免责声明:
1. 本站资源转自互联网,源码资源分享仅供交流学习,下载后切勿用于商业用途,否则开发者追究责任与本站无关!
2. 本站使用「署名 4.0 国际」创作协议,可自由转载、引用,但需署名原版权作者且注明文章出处
3. 未登录无法下载,登录使用金币下载所有资源。
IT小站 » 使用NestJS构建GraphQL API

常见问题FAQ

没有金币/金币不足 怎么办?
本站已开通每日签到送金币,每日签到赠送五枚金币,金币可累积。
所有资源普通会员都能下载吗?
本站所有资源普通会员都可以下载,需要消耗金币下载的白金会员资源,通过每日签到,即可获取免费金币,金币可累积使用。

发表评论