DEV Community

Cover image for มาลองใช้ NestJS ทำ GraphQL Server กัน (ฉบับผู้เริ่มต้น)
NotAllow
NotAllow

Posted on • Edited on

4 1

มาลองใช้ NestJS ทำ GraphQL Server กัน (ฉบับผู้เริ่มต้น)

ทุกวันนี้ผมใช้ express + apollo ทำ GraphQL Server แต่ปีนี้ในทีมก็มีมติว่าจะเปลี่ยนไปเขียน TypeScript ซึ่งจะตอบโจทย์ในเรื่องของ NewBie Mistakes ตอนแรกว่าจะเขียนไว้อ่านเอง แต่ก็อยากมาแชร์ให้ทุก ๆ คนมาลองดูกันครับ

มาทำความรู้จักกันครับว่า NestJS คืออะไร

NestJS อย่างที่หลาย ๆ คนทราบกันดีอยู่แล้วว่ามันคือ Framework ตัวนึงที่เขียนด้วย TypeScript และออกแบบมาโดยใช้แนวคิด OOP กับ Fuctional Programming เข้าด้วยกัน ซึ่ง NestJS ก็อาศัยการทำงานของ HTTP Server ที่เราสามารถเลือกใช้ได้ก็จะเป็น Express หรือ Fastify ในบทความนี้ผมขอใช้ Express แล้วกันนะครับ

มาเริ่มกันเลยดีกว่า

ติดตั้ง Nest CLI กันก่อน ด้วย Command ตามนี้

$ npm i -g @nestjs/cli
Enter fullscreen mode Exit fullscreen mode

เสร็จแล้วก็สร้างโปรเจค

$ nest new nestjs-graphql-starter
Enter fullscreen mode Exit fullscreen mode

แล้วมันจะขึ้นให้เลือก package manager ว่าจะใช้ npm หรือ yarn ในทีนี้ผมก็เลือก yarn นะครับ

Which package manager would you ❤️  to use? npm or yarn
Enter fullscreen mode Exit fullscreen mode

เท่านี้ก็จะได้ Nestjs project structer มาแล้วครับ ต่อมาเราจะมาเริ่มใช้ GrahpQL ร่วมกับ NestJS กัน

ก่อนอื่นก็มาติดตั้ง GraphQL กันด้วยคำสั่ง

$ yarn add @nestjs/graphql graphql-tools graphql // or npm i --save @nestjs/graphql graphql-tools graphql
Enter fullscreen mode Exit fullscreen mode

ต่อมาติดติ้ง Http server จะเลือกใช้ตัวไหนก็ได้ระหว่าง express กับ fastify

กรณีเลือกใช้ express ใช้คำสั่ง

$ yarn add apollo-server-express // or npm i --save apollo-server-express
Enter fullscreen mode Exit fullscreen mode

กรณีเลือกใช้ fastify ใช้คำสั่ง

$ yarn add apollo-server-fastify // or npm i --save apollo-server-fastify
Enter fullscreen mode Exit fullscreen mode

เข้า Folder ที่สร้างเมื่อกี้ด้วย Editor Tool แล้วหาไฟล์ nest-cli.json ใส่ code ตามนี้

{
  "compilerOptions": {
    "plugins": ["@nestjs/graphql/plugin"]
  }
}
Enter fullscreen mode Exit fullscreen mode

ต่อมาแก้ไขไฟล์ ./src/app.module.ts เพื่อเรียกใช้งาน graphql ตาม code ด้านล่างนี้ได้เลยครับ

import { Module } from '@nestjs/common'
import { GraphQLModule } from '@nestjs/graphql'

@Module({
  imports: [
    GraphQLModule.forRoot({
      installSubscriptionHandlers: true,
      autoSchemaFile: 'schema.gql',
      debug: false,
      playground: true,
    }),
  ],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

จาก code ด้านบน

installSubscriptionHandlers: true ไว้สำหรับเลือกเปิดใช้งาน Subscription หรือไม่
autoSchemaFile: 'schema.gql' ไว้ generate file typeDefs schema เพื่อนำไปไว้ Build เพื่อ Run Apollo Server
debug: false ไว้สำหรับจะเลือกใช้งาน debug หรือไม่
playground: true ไว้สำหรับเลือกเปิดใช้งาน playgroud client หรือไม่

ต่อมาพระเอกของเรากันดีกว่า Nest มี CLI ไว้สร้าง Module,Interface,Resolver,Service
มาสร้าง module กัน ด้วยคำสั่ง

$ nest g module {name} //or nest g mo {name}
Enter fullscreen mode Exit fullscreen mode

ตัวอย่างผมจะสร้าง module ชื่อ book ก็ใช้คำสั่ง

$ nest g mo book
Enter fullscreen mode Exit fullscreen mode
$ nest g resolver {name} //or nest g r {name}
Enter fullscreen mode Exit fullscreen mode

ตัวอย่างผมจะสร้าง Resolver ชื่อ book ก็ใช้คำสั่ง

$ nest g r book
Enter fullscreen mode Exit fullscreen mode

ทีนี้ NestJS ก็ได้ออก Decorator ของตัวเองเพื่อทำ DTO (Data Transfer Object) ไว้แล้ว โดยที่เมื่อก่อนยืมของ TypeGraphQL มาใช้ก่อน งั้นเรามาเริ่มสร้าง Model กัน
สร้างโดยการ Create Folder ให้อยู่ใน Directory Book ที่ ./src/book/models/book.model.ts

import { Field, ID, ObjectType } from '@nestjs/graphql'

@ObjectType()
export class Book {
  @Field(type => ID)
  id: string

  @Field(type => String, { nullable: true })
  name?: string

  @Field(type => String, { nullable: true })
  description?: string

  @Field(type => Number, { nullable: true })
  price?: number

  @Field(type => [String], { nullable: true })
  writer?: string[]
}
Enter fullscreen mode Exit fullscreen mode

ถ้าต้องการให้ Field มีค่าเป็น null ได้ ให้ใส่ options เพิ่มคือ { nullable: true } และใส่ ? หลังตัวแปรเพื่อละเว้นให้เป็น optional ได้

เสร็จแล้วสร้าง DTO ไว้หรับ Type Input กันเถอะเพื่อไปใช้เป็น Variable ตอนเรียกใช้งานกัน

create folder dto ให้อยู่ใน Directory Book ที่ ./src/book/dto
แล้ว create file book.input.ts อยู่ใน folder dto
เมื่อสร้างแล้วเขียน code ตามนี้เลยครับ

import { Field, InputType } from '@nestjs/graphql'

@InputType()
export class InputBook {
  @Field(type => String)
  name: string

  @Field(type => Number, { nullable: true })
  price?: number

  @Field(type => String, { nullable: true })
  description?: string

  @Field(type => [String])
  writer: string[]
}
Enter fullscreen mode Exit fullscreen mode

ถ้าต้องการให้ Field ไหนเป็น Array ให้ใส่ [] คอบ Type นั้นได้เลยครับ

มาจัดการกับ Resolver กัน ในบทความที่ผมเขียนนี้จะยกการทำ Mutation กับ Query ไว้เท่านี้ก่อนนะครับเพื่อไม่ให้บทความมีความยาวมากเกินไป

กลับมาที่ File : book.resolver.ts แล้วเขียน Code สร้าง Mutation กับ Query กันตามนี้เลยครับ ขออนุญตาติฟิกค่า return เลยนะครับ

import { Resolver, Query, Mutation, Args } from '@nestjs/graphql'
import { Book } from './models/book.model'
import { InputBook } from './dto/book.input'

@Resolver('Book')
export class BookResolver {
  @Query(returns => Book)
  getBook(): Book {
    const result: Book = {
      id: '1',
      name: 'BeforeSecond',
      price: 199,
    }
    return result
  }

  @Mutation(returns => Book)
  createBook(@Args('input') input: InputBook): Book {
    const result: Book = {
      id: '2',
      ...input,
    }
    return result
  }
}
Enter fullscreen mode Exit fullscreen mode

เสร็จแล้วลองรันกันครับ

$ yarn start:dev
Enter fullscreen mode Exit fullscreen mode

เข้า Web Browser เปิด URL: http://localhost:3000/graphql

ทดสอบ Query กัน

ใส่ Code Query ดังนี้

query {
  getBook{
    id
    name
    price
    description
    writer
  }
}
Enter fullscreen mode Exit fullscreen mode

ปรากฏว่าได้ผลลัพทธ์

{
  "data": {
    "getFirst": {
      "id": "1",
      "name": "first"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

ทดสอบ Mutation กัน

mutation {
  createBook(input:{
    name:"test",
    description:"ทดสอบ",
    price:299,
    writer:["First","BeforeSecond"]
  }){
    id
    name
    price
    description
    writer
  }
}
Enter fullscreen mode Exit fullscreen mode

ผลลัพท์

{
  "data": {
    "createBook": {
      "id": "2",
      "name": "test",
      "price": 299,
      "description": "ทดสอบ",
      "writer": [
        "First",
        "BeforeSecond"
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Very Good 👍👍👍👍👍

สรุปได้ว่า NestJS ก็เป็นอีกทางเลือกนึงที่สามารถทำ GraphQL Server ได้ด้วยการเขียน TypeScript ที่ผมคิดว่าตอบโจทย์ได้ดีเลยทีเดียวครับ โดยปกติถ้าเขียน Express+Apollo เราจะต้องมานั่งทำ typeDefs เอง หรือบ้างก็ไปใช้ CLI codegen:generate แต่ NestJS ทำให้เราสะดวกมากขึ้นไปเยอะเลย ยิ่งถ้าใช้ TypeORM หรือ Sequelize นี่ยิ่งสบายเลยกับการเขียน GraphQL มาก ๆ เลยครับ

สุดท้ายนี้ ถ้าผิดพลาดต้องขอภัยด้วยนะครับ ขอบคุณที่อ่านมาจนจบครับผม 😀
สามารถศึกษาเพิ่มเติมได้ที่
Referense: https://docs.nestjs.com/graphql/quick-start

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (1)

Collapse
 
adrinalin4ik profile image
Alex Panfilkin

You can also try to use this one npmjs.com/package/nestjs-graphql-t...

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay