NestJS ตั้งแต่ศูนย์: ระบบจัดการหนังสือ

ตั้งแต่ติดตั้งเครื่องมือ สร้างโฟลเดอร์ รัน npm จนยิง API ได้ พร้อมลิงก์เรียนรู้ CRUD และ Swagger แยกภาษาไทยและภาษาอังกฤษ

วิธีเริ่มต้น

1ติดตั้ง Node.js

ดาวน์โหลดเวอร์ชัน LTS จาก nodejs.org (npm จะติดมาด้วย) แล้วเช็คใน terminal

node -v
npm -v

2ติดตั้ง Nest CLI

เครื่องมือบรรทัดคำสั่งของ NestJS ติดตั้งครั้งเดียวใช้ได้ทุกโปรเจกต์

npm i -g @nestjs/cli
nest --version

ถ้าขึ้น nest is not recognized ให้ปิดแล้วเปิด terminal ใหม่ ส่วน Windows PowerShell ที่ติด execution policy ให้ใช้ Command Prompt แทน

3สร้างโฟลเดอร์และโปรเจกต์

เลือกที่เก็บงาน แล้วให้ Nest สร้างโฟลเดอร์โปรเจกต์ให้เอง (ไม่ต้อง mkdir ชื่อโปรเจกต์) เลือก npm เมื่อถูกถาม

mkdir projects && cd projects
nest new library-api
cd library-api

4รันครั้งแรก

npm run start:dev

เปิด http://localhost:3000 จะเห็น Hello World! โหมดนี้รีสตาร์ทเองทุกครั้งที่เซฟไฟล์ (หยุดด้วย Ctrl+C)

5ติดตั้งแพ็กเกจเพิ่ม

npm install class-validator class-transformer @nestjs/swagger

สองตัวแรกใช้ตรวจความถูกต้องของข้อมูล (ตอบ 400) ตัวที่สามสร้างหน้าเอกสาร API ที่ /docs

6สร้างโครง CRUD

nest g resource books

เลือก REST API และตอบ Yes ตอนถามเรื่อง CRUD entry points จะได้ module, controller, service, DTO และ entity ครบ จากนั้นนำโค้ดของ books.controller.ts, books.service.ts, book.dto.ts ที่ผมให้ไว้ก่อนหน้านี้มาวางทับ

ตัวสร้างอัตโนมัติใช้ PATCH สำหรับแก้ไข แต่โจทย์ของเราใช้ PUT จึงต้องแก้ใน controller ตามโค้ดที่ให้ไว้

ไฟล์หน้าที่
books.controller.tsกำหนด route GET/POST/PUT/DELETE
books.service.tsตรรกะและข้อมูลจำลอง
dto/book.dto.tsรูปแบบข้อมูลและ validation

7เปิด Validation และ Swagger ใน main.ts

import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  const cfg = new DocumentBuilder().setTitle('Library API').build();
  SwaggerModule.setup('docs', app, SwaggerModule.createDocument(app, cfg));
  await app.listen(3000);
}
bootstrap();

8ทดสอบ

เปิด http://localhost:3000/docs แล้วกด Try it out หรือใช้ curl

curl http://localhost:3000/books
curl -i http://localhost:3000/books/999   # ได้ 404
คำสั่งใช้ทำอะไร
npm run start:devรันตอนพัฒนา (auto reload)
npm run buildคอมไพล์เป็นโฟลเดอร์ dist
npm run start:prodรันจากโค้ดที่ build แล้ว
npm run testรันเทสต์

ปัญหาที่พบบ่อย

Cannot find module './dto/book.dto' แปลว่าไฟล์ไม่ได้อยู่ที่ src/books/dto/book.dto.ts หรือชื่อสะกดไม่ตรง
EADDRINUSE แปลว่าพอร์ต 3000 ถูกใช้อยู่ ให้ปิดโปรเจกต์เดิมหรือเปลี่ยนพอร์ตใน listen()

การใช้ Swagger

Swagger ทำอะไรได้

สร้างหน้าเอกสาร API ให้อัตโนมัติจากโค้ด เปิดที่ /docs เห็นทุก endpoint และกด Try it out เพื่อยิง API ทดสอบได้เลย (ตั้งค่าใน main.ts ตามขั้นที่ 7 ด้านบน)

DTO ใส่ @ApiProperty({ example: ... }) เพื่อให้ช่อง Request body มีตัวอย่างข้อมูล

Controller ใส่ decorator เหล่านี้เพื่อบอกสถานะที่ตอบกลับ

import { ApiTags, ApiOperation, ApiOkResponse,
  ApiCreatedResponse, ApiNotFoundResponse } from '@nestjs/swagger';

@ApiTags('books')            // จัดกลุ่มหัวข้อ
@Controller('books')
export class BooksController {
  @Get(':id')
  @ApiOperation({ summary: 'ดึงหนังสือเล่มเดียว' })
  @ApiOkResponse({ description: 'พบหนังสือ (200)' })
  @ApiNotFoundResponse({ description: 'ไม่พบหนังสือ (404)' })
  findOne(@Param('id', ParseIntPipe) id: number) { ... }

  @Post()
  @ApiCreatedResponse({ description: 'สร้างสำเร็จ (201)' })
  create(@Body() dto: BookDto) { ... }
}

ถ้าอยากไม่ต้องเขียน @ApiProperty ทุกฟิลด์ ให้เปิด CLI plugin โดยเพิ่ม @nestjs/swagger ใน nest-cli.json (ดูลิงก์หัวข้อ “เรื่อง Swagger” ท้ายหน้า)

🧱 โค้ดเต็มฝั่ง Backend (NestJS) ระบบ books

ไฟล์ครบทุกตัวของโปรเจกต์ library-api ที่สร้างด้วย nest g resource books วางทับได้เลย ข้อมูลเก็บในหน่วยความจำ (รีสตาร์ตแล้วหาย) field ใช้ title, author, price ถ้า DTO เดิมของคุณต่างจากนี้ให้ปรับให้ตรงกัน

โครงไฟล์

library-api/
└─ src/
   ├─ main.ts
   ├─ app.module.ts
   └─ books/
      ├─ books.module.ts
      ├─ books.controller.ts
      ├─ books.service.ts
      ├─ dto/book.dto.ts
      └─ entities/book.entity.ts

ไฟล์ใน src/books

app.module.ts และ main.ts

ใน main.ts เพิ่ม enableCors เพื่อให้ Next.js (พอร์ต 3001) เรียก API ได้ และเปิด whitelist ให้ตัด field แปลกปลอมทิ้ง

🖥️ ฝั่ง Frontend (Next.js) ต่อกับ books

ใช้ App Router + TypeScript หน้าแรกเป็น Server Component ดึงรายการหนังสือ ส่วนฟอร์มเพิ่ม/แก้ไขและปุ่มลบเป็น Client Component

1สร้างโปรเจกต์ Next.js

เปิด terminal ใหม่ ออกจากโฟลเดอร์ library-api แล้วสร้างโปรเจกต์ข้างๆ (ถ้ามีคำถามเพิ่ม เช่น React Compiler หรือ Turbopack ให้กด Enter ใช้ค่าเริ่มต้น)

cd ..
npx create-next-app@latest library-web --typescript --app --no-tailwind --eslint --no-src-dir --import-alias "@/*"
cd library-web

2ตั้งพอร์ตเป็น 3001

Nest ใช้พอร์ต 3000 อยู่แล้ว แก้ส่วน scripts ใน package.json

แล้วสร้างไฟล์ .env.local ที่รากโปรเจกต์ (ค่าที่ขึ้นต้น NEXT_PUBLIC_ ใช้ได้ทั้งฝั่ง server และ browser)

3โครงไฟล์

library-web/
├─ .env.local
├─ lib/api.ts
├─ components/
│  ├─ BookForm.tsx
│  └─ DeleteButton.tsx
└─ app/
   ├─ globals.css
   ├─ layout.tsx
   ├─ page.tsx                  (รายการ)
   └─ books/
      ├─ new/page.tsx           (เพิ่ม)
      └─ [id]/edit/page.tsx     (แก้ไข)

สร้างโฟลเดอร์ lib และ components ที่รากโปรเจกต์เอง ส่วนไฟล์ใน app ให้วางทับไฟล์เดิม (ลบ app/page.module.css ทิ้งได้)

4ตัวเรียก API

5Components (Client)

6หน้าเว็บใน app/

7รันทั้งสองฝั่งและทดสอบ

เปิด 2 terminal แยกกัน

# terminal 1 (backend พอร์ต 3000)
cd library-api
npm run start:dev

# terminal 2 (frontend พอร์ต 3001)
cd library-web
npm run dev

เปิด http://localhost:3001 ควรเห็นหนังสือ 2 เล่มจาก Nest ลองกดเพิ่ม แก้ไข และลบ แล้วเช็คที่ http://localhost:3000/docs ว่าข้อมูลตรงกัน

อาการสาเหตุและวิธีแก้
fetch failed / ECONNREFUSEDBackend ยังไม่รัน หรือ NEXT_PUBLIC_API_URL ผิด (แก้ .env.local แล้วต้องรีสตาร์ต npm run dev)
CORS error ใน browserลืม enableCors ใน main.ts หรือยังไม่รีสตาร์ต Nest
กดบันทึกแล้วได้ 400ข้อมูลไม่ผ่าน validation เช่น ชื่อว่าง หรือราคาติดลบ
Cannot find module '@/lib/api'โฟลเดอร์ lib ต้องอยู่ที่รากโปรเจกต์ (ไม่ใช่ใน app) และ import alias ต้องเป็น @/*

⚡ ฟังก์ชันของ Next.js ที่ใช้บ่อย

กดหัวข้อเพื่อดูฟังก์ชัน ตัวอย่าง และผลลัพธ์ อ้างอิงจาก App Router ถ้าใช้คนละเวอร์ชัน (บางส่วนเปลี่ยนใน Next 15 และ 16) ให้เทียบกับ nextjs.org/docs

📘 ฟังก์ชันจัดการตัวแปรแต่ละชนิดใน TypeScript

กดหัวข้อเพื่อเปิดดูตาราง ฟังก์ชัน ตัวอย่าง และผลลัพธ์ แต่ละแถวเป็นอิสระต่อกัน (ไม่ต่อเนื่องจากแถวก่อนหน้า) บางฟังก์ชัน เช่น replaceAll, at, Promise.any ต้องตั้ง target หรือ lib ใน tsconfig เป็น ES2022 ขึ้นไป (โปรเจกต์ NestJS รุ่นใหม่ตั้งไว้ให้แล้ว)

🇹🇭 เว็บภาษาไทยเรื่อง NestJS CRUD

พบ 9 ลิงก์ (บทความไทยมีน้อย) หลายชิ้นเก่า 2–5 ปี คำสั่งบางอย่างอาจเปลี่ยนไปแล้ว ให้เทียบกับ docs.nestjs.com

ตรงเรื่อง CRUD
1. สร้าง RESTful APIs ด้วย NestJS ตอนที่ 4Medium: ทำ CRUD กับฐานข้อมูลด้วย TypeORM แยกตามความสัมพันธ์ของตาราง พร้อมเตือนจุดที่ error บ่อย (เป็นตอนที่ 4 ของชุด)medium.com/@slil.puangpoom 2. พัฒนา CRUD + Role-based Authentication ตอนที่ 1Medium: สอน Create/Read/Update/Delete ของ user อธิบาย DTO และการกำหนด path ใกล้เคียงโจทย์ของเรามากที่สุดmedium.com/@erika.snp 3. สร้าง RESTful API ด้วย NestJS และ MongoDBmeesiri.com: บล็อกบริษัท เนื้อหาเชิงภาพรวม ตั้งแต่ติดตั้ง NestJS CLI ถึงต่อ MongoDBmeesiri.com/blog/…/sraang-restful-api-dwy-nestjs-aela-mongodb-2104 4. พื้นฐาน NestJS ทำ API CRUD ข้อมูล MySQLYouTube: วิดีโอ live code เหมาะกับคนชอบดูมากกว่าอ่าน (ลงมาประมาณ 4–5 ปีแล้ว)youtube.com/watch?v=zY2dU54X08E 5. คอร์ส RESTful API NestJS + TypeORM + GraphQL + MySQLSkillLane: คอร์สออนไลน์ภาษาไทย สอน REST API, TypeORM และล็อกอินด้วย JWT (ยังไม่ทราบว่าต้องเสียเงินหรือไม่)skilllane.com/courses/RESTful-API-NestJS-TypeORM-GraphQL-MySQL
เกี่ยวข้อง แต่ไม่ใช่ CRUD ตรงๆ
6. Learning Management System (Prisma + PostgreSQL + Docker)GitHub: โปรเจกต์ตัวอย่างพร้อม README ภาษาไทย เหมาะดูโครงสร้างงานจริง (ผู้เขียนบอกว่ายังไม่มี validation ละเอียด)github.com/nut2567/Learning_Management_System_PostgreSql 7. สร้าง API ด้วย NestJS GraphQL ฉบับนักพัฒนาไทยmeesiri.com: ทำ API ด้วย GraphQL แทน RESTmeesiri.com/blog/…/sraang-api-dwy-nestjs-graphql-…-1989 8. รวมบทความ Node.js ของ meesiri.comหน้ารวมบทความ มี “คู่มือสร้าง RESTful API ด้วย NestJS ฉบับนักพัฒนาไทย” ต้องกดเลือกจากหน้านี้meesiri.com/blog/tag/node-js-814
เรื่อง Swagger
9. Mintelligence: NestJS OpenApi (Swagger)Medium: เรื่อง Swagger (เก่า ใช้ชื่อ ApiModelProperty ปัจจุบันใช้ ApiProperty)medium.com/mintelligence/openapi-4824dba1ab86

🇬🇧 เว็บภาษาอังกฤษเรื่อง NestJS CRUD