ข้ามไปยังเนื้อหา

Backend Init

แอปพลิเคชัน NestJS ที่ apps/api ต่อสายให้อ่านพอร์ตจาก root .env ของ monorepo ผ่าน @nestjs/config พร้อม dependency ทุกตัวที่คอร์สที่เหลือต้องการติดตั้งไว้แล้ว

Nest CLI (nest new) สร้างโครงสร้าง module/controller/service, tsconfig.json และการตั้งค่าเทสต์ที่ทุกบทเรียนถัดไปต่อยอด การเขียน boilerplate ชุดนั้นเองไม่ได้อะไรเพิ่ม แถมเสี่ยงได้ config ที่เพี้ยนจากที่คอร์สคาดไว้นิดหน่อย ส่วน @nestjs/config รวมการเข้าถึง environment ไว้ที่เดียวผ่าน ConfigService ที่มี type แทนที่จะปล่อยให้อ่าน process.env ดิบ ๆ กระจายไปทั่วโค้ด

nest new เทียบกับ npm init เอง CLI ต่อสาย ESLint, Jest, tsconfig.json และ nest-cli.json ของ Nest ให้ในขั้นตอนเดียว และทุก scaffold ออกมาหน้าตาเหมือนกัน ซึ่งสำคัญมากตอนเรียนตามคอร์ส ต้นทุนคือ CLI มองว่านี่เป็นโปรเจกต์เดี่ยว ๆ ค่าเริ่มต้นจึงสร้าง git repo ของตัวเองขึ้นมา ซึ่งเราไม่ต้องการใน monorepo ที่ git init ไว้ที่ root แล้ว จึงใส่ --skip-git เพื่อเลี่ยง repository ซ้อนกัน และ --package-manager npm เพื่อเลี่ยง prompt แบบโต้ตอบ

ติดตั้ง dependency รวดเดียว เทียบกับติดตั้งทีละตัวตอนใช้จริง ติดตั้งทุกอย่างตอนนี้เลย (GraphQL, Mongoose, auth, validation) แปลว่าขั้นตอน npm install ของทุกโมดูลถัดไปเสร็จไปแล้ว และสร้าง package-lock.json ครั้งเดียวจบ สิ่งที่แลกคือการติดตั้งรอบแรกนานขึ้น และ package.json มี dependency ของ GraphQL กับ auth ตั้งแต่ยังไม่มี resolver หรือ guard สักตัว ตรงนี้ยอมรับได้ เพราะลิสต์ dependency ของคอร์สคงที่และรู้ล่วงหน้าอยู่แล้ว

Scaffold API เข้าไปที่ apps/api โดยข้าม git repo ที่ซ้อนกัน เพราะ root ของ monorepo มี git ของตัวเองอยู่แล้ว:

Terminal window
cd devblog
nest new apps/api --package-manager npm --skip-git
cd apps/api

nest new เพิ่ม @nestjs/core, @nestjs/common และ @nestjs/platform-express ลงใน package.json ให้แล้ว ไม่ต้องติดตั้งซ้ำ ที่เหลือติดตั้งตามนี้ จัดกลุ่มตามหน้าที่ของแต่ละชุด:

Terminal window
# env vars from the root .env, via ConfigService
npm install @nestjs/config
# code-first GraphQL, served at /graphql by Apollo Server
npm install @nestjs/graphql @nestjs/apollo @apollo/server graphql
# MongoDB models and schemas via Mongoose
npm install @nestjs/mongoose mongoose
# JWT auth: Passport strategy, JWT signing/verification, password hashing
npm install @nestjs/passport passport passport-jwt @nestjs/jwt bcrypt
# DTO and GraphQL input validation
npm install class-validator class-transformer
# deterministic, URL-safe post slugs
npm install slugify
# type definitions for the auth packages above
npm install -D @types/passport-jwt @types/bcrypt

แก้ src/app.module.ts ให้โหลด root .env แบบ global:

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: '../../.env',
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

envFilePath resolve จากตำแหน่งที่ process ของ Nest รันอยู่ (apps/api) ดังนั้น ../../.env จึงชี้ไปที่ devblog/.env ไฟล์ที่ Repo layout สร้างไว้ ส่วน isGlobal: true แปลว่าโมดูลไหนต่อจากนี้ก็ inject ConfigService ได้โดยไม่ต้อง import ConfigModule ซ้ำ

แก้ src/main.ts ให้ฟังที่ API_PORT แทนพอร์ตที่ hardcode ไว้:

import { NestFactory } from '@nestjs/core';
import { ConfigService } from '@nestjs/config';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const configService = app.get(ConfigService);
const port = configService.get<number>('API_PORT') ?? 4000;
await app.listen(port);
console.log(`API listening on http://localhost:${port}`);
}
bootstrap();

สตาร์ตแบบ watch mode:

Terminal window
npm run start:dev

คอนโซลควรพิมพ์ log การ bootstrap ของ Nest จบด้วยบรรทัดที่คุณเพิ่มเอง:

[Nest] ... LOG [NestApplication] Nest application successfully started
API listening on http://localhost:4000

ในอีก terminal หนึ่ง:

Terminal window
curl http://localhost:4000
# Hello World!

Hello World! คือ response ค่าเริ่มต้นจากคู่ AppController/AppService ที่ scaffold มาให้ เห็นข้อความนี้แปลว่าแอปบูตสำเร็จ ConfigService อ่าน API_PORT ได้ถูกต้อง (4000 จาก .env) และ HTTP server เข้าถึงได้แล้ว

apps/api คือแอปที่ Nest CLI scaffold ให้ พร้อม dependency ของคอร์สครบทุกตัวตั้งแต่ต้น จัดกลุ่มตามหน้าที่: @nestjs/config สำหรับเข้าถึง environment, GraphQL/Apollo สำหรับเลเยอร์ API, Mongoose สำหรับ MongoDB, Passport/JWT/bcrypt สำหรับ auth, class-validator/class-transformer สำหรับ validation และ slugify สำหรับ slug ของโพสต์ ตอนนี้ main.ts อ่านพอร์ตจาก root .env ผ่าน ConfigService ที่มี type แทนตัวเลข hardcode และ npm run start:dev ยืนยันแล้วว่าบูตขึ้นที่พอร์ต 4000

ถัดไป: Frontend init →