มาลองใช้ NestJS ทำ GraphQL Server กัน (ฉบับผู้เริ่มต้น)
NotAllow
Posted on April 11, 2020
ทุกวันนี้ผมใช้ 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
เสร็จแล้วก็สร้างโปรเจค
$ nest new nestjs-graphql-starter
แล้วมันจะขึ้นให้เลือก package manager ว่าจะใช้ npm
หรือ yarn
ในทีนี้ผมก็เลือก yarn
นะครับ
Which package manager would you ❤️ to use? npm or yarn
เท่านี้ก็จะได้ Nestjs project structer มาแล้วครับ ต่อมาเราจะมาเริ่มใช้ GrahpQL ร่วมกับ NestJS กัน
ก่อนอื่นก็มาติดตั้ง GraphQL กันด้วยคำสั่ง
$ yarn add @nestjs/graphql graphql-tools graphql // or npm i --save @nestjs/graphql graphql-tools graphql
ต่อมาติดติ้ง Http server จะเลือกใช้ตัวไหนก็ได้ระหว่าง express กับ fastify
กรณีเลือกใช้ express ใช้คำสั่ง
$ yarn add apollo-server-express // or npm i --save apollo-server-express
กรณีเลือกใช้ fastify ใช้คำสั่ง
$ yarn add apollo-server-fastify // or npm i --save apollo-server-fastify
เข้า Folder ที่สร้างเมื่อกี้ด้วย Editor Tool แล้วหาไฟล์ nest-cli.json
ใส่ code ตามนี้
{
"compilerOptions": {
"plugins": ["@nestjs/graphql/plugin"]
}
}
ต่อมาแก้ไขไฟล์ ./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 {}
จาก 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}
ตัวอย่างผมจะสร้าง module ชื่อ book ก็ใช้คำสั่ง
$ nest g mo book
$ nest g resolver {name} //or nest g r {name}
ตัวอย่างผมจะสร้าง Resolver ชื่อ book ก็ใช้คำสั่ง
$ nest g r book
ทีนี้ 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[]
}
ถ้าต้องการให้ 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[]
}
ถ้าต้องการให้ 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
}
}
เสร็จแล้วลองรันกันครับ
$ yarn start:dev
เข้า Web Browser เปิด URL: http://localhost:3000/graphql
ทดสอบ Query กัน
ใส่ Code Query ดังนี้
query {
getBook{
id
name
price
description
writer
}
}
ปรากฏว่าได้ผลลัพทธ์
{
"data": {
"getFirst": {
"id": "1",
"name": "first"
}
}
}
ทดสอบ Mutation กัน
mutation {
createBook(input:{
name:"test",
description:"ทดสอบ",
price:299,
writer:["First","BeforeSecond"]
}){
id
name
price
description
writer
}
}
ผลลัพท์
{
"data": {
"createBook": {
"id": "2",
"name": "test",
"price": 299,
"description": "ทดสอบ",
"writer": [
"First",
"BeforeSecond"
]
}
}
}
Very Good 👍👍👍👍👍
สรุปได้ว่า NestJS ก็เป็นอีกทางเลือกนึงที่สามารถทำ GraphQL Server ได้ด้วยการเขียน TypeScript ที่ผมคิดว่าตอบโจทย์ได้ดีเลยทีเดียวครับ โดยปกติถ้าเขียน Express+Apollo เราจะต้องมานั่งทำ typeDefs เอง หรือบ้างก็ไปใช้ CLI codegen:generate แต่ NestJS ทำให้เราสะดวกมากขึ้นไปเยอะเลย ยิ่งถ้าใช้ TypeORM หรือ Sequelize นี่ยิ่งสบายเลยกับการเขียน GraphQL มาก ๆ เลยครับ
สุดท้ายนี้ ถ้าผิดพลาดต้องขอภัยด้วยนะครับ ขอบคุณที่อ่านมาจนจบครับผม 😀
สามารถศึกษาเพิ่มเติมได้ที่
Referense: https://docs.nestjs.com/graphql/quick-start
Posted on April 11, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.