Skip to content
← All Skills
💚

Node.js

JavaScript runtime สำหรับ backend — ใช้สร้าง web application และ API services

What I Can Do

  • สร้าง RESTful APIs ด้วย Express / Fastify
  • ใช้ Node.js เป็น backend สำหรับ full-stack applications
  • จัดการ npm packages และ monorepo workflows
  • เขียน build scripts และ automation tools
  • ใช้ Node.js runtime สำหรับ Next.js server

Commands I Use Daily

bash
# run development server
npm run dev

# install dependencies
npm install

# install specific package
npm install express

# install dev dependency
npm install -D typescript @types/node

# run script ที่ define ใน package.json
npm run build

# execute package binary โดยไม่ต้อง install globally
npx prisma migrate dev

# ดู outdated packages
npm outdated

# audit security vulnerabilities
npm audit

Event Loop

Node.js ใช้ single-threaded event loop — ไม่ได้หมายความว่า handle ได้ทีละ request แต่ใช้ non-blocking I/O ทำให้ handle concurrent requests ได้เยอะ I/O operations (file, network, database) ถูกส่งไป OS/thread pool แล้ว callback เมื่อเสร็จ

Modules (CommonJS vs ESM)

  • CommonJSrequire() / module.exports, synchronous, default ใน Node.js
  • ES Modulesimport / export, async, ใช้ "type": "module" ใน package.json
  • โปรเจคใหม่แนะนำใช้ ESM เพราะเป็น standard ของ JavaScript

npm & package.json

  • package.json — define project metadata, scripts, dependencies
  • package-lock.json — lock exact versions สำหรับ reproducible installs
  • scripts — define custom commands เช่น "dev": "next dev", "build": "tsc"
  • dependencies vs devDependencies — runtime vs build-time packages

Express / Fastify

  • Express — minimal, flexible, middleware-based web framework
  • Fastify — performance-focused, schema-based validation, plugin system
  • ทั้งสองใช้ middleware pattern สำหรับ request processing pipeline

ตัวอย่าง Express middleware pattern: app.use(cors()), app.use(express.json()), app.use("/api/users", userRouter) — chain middleware ตามลำดับ

Middleware Pattern

Middleware = function ที่ run ระหว่าง request กับ response — ใช้สำหรับ logging, authentication, error handling, request parsing, CORS chain ของ middleware ทำงานตามลำดับ

Error Handling

Express error handler middleware รับ 4 parameters (err, req, res, next) — log error ด้วย console.error(err.stack), ส่ง status code กลับด้วย res.status(err.status || 500) พร้อม error message

ใช้ express-async-errors หรือ wrap async handlers เพื่อ catch async errors อัตโนมัติ

Streams

Streams ใน Node.js ใช้ process data ทีละ chunk — ไม่ต้องโหลดทั้งหมดเข้า memory, 4 types: Readable, Writable, Duplex, Transform ใช้สำหรับ file processing, HTTP requests/responses

Environment Variables

ใช้ process.env อ่าน environment variables — เก็บ secrets, config ที่เปลี่ยนตาม environment ใช้ .env file + dotenv package สำหรับ development, ไม่ commit .env เข้า git

Process Management (PM2)

PM2 = production process manager สำหรับ Node.js — auto-restart เมื่อ crash, cluster mode สำหรับ multi-core, log management, monitoring

File System (fs)

ตัวอย่าง: import จาก "fs/promises" แล้วใช้ await readFile("config.json", "utf-8") แล้ว JSON.parse(data) ได้ config object

ใช้ fs/promises (async) แทน callback-based fs — cleaner code ด้วย async/await

Worker Threads

Worker threads สำหรับ CPU-intensive tasks — แยก heavy computation ออกจาก event loop ไม่ให้บล็อก I/O, communicate ผ่าน postMessage

ปัญหาที่เจอบ่อย & วิธีแก้

Unhandled Promise Rejections ทำ process crash

Node.js process crash โดยไม่มี error message ที่ชัดเจน

สาเหตุ: async function throw error โดยไม่มี catch, ลืม await promise, หรือ callback-based code ที่ migrate มา async/await ไม่ครบ — Node.js v15+ default terminate process เมื่อ unhandled rejection

วิธีแก้:

  • ใช้ process.on('unhandledRejection', (reason) => { logger.error(reason); }) จับ globally เป็น safety net
  • ใช้ async/await + try-catch ทุกที่ที่มี async operation
  • ใน Express ใช้ express-async-errors package หรือ wrap handler: const asyncHandler = fn => (req, res, next) => fn(req, res, next).catch(next)

Memory Leaks — process กิน RAM เพิ่มขึ้นเรื่อยๆ

Node.js process ใช้ memory เพิ่มขึ้นเรื่อยๆ จน OOM killed

สาเหตุ: event listeners ที่ add แล้วไม่ remove (เช่น emitter.on() ใน loop), closures ที่ hold reference ไปยัง objects ขนาดใหญ่, global variables/caches ที่สะสม data ไม่มี eviction

วิธีแก้:

  • ใช้ node --inspect + Chrome DevTools → Memory tab → Heap snapshot เปรียบเทียบ 2 snapshots หา objects ที่โตขึ้น
  • สังเกต warning MaxListenersExceededWarning — สัญญาณว่า add listeners ซ้ำ
  • ใช้ WeakMap/WeakRef สำหรับ caches ที่ไม่ต้องการ keep reference
  • ตรวจว่า cleanup ครบ: removeListener, close database connections, clear intervals

Event Loop Blocking — server ไม่ respond

ทุก request ค้างพร้อมกัน server ไม่ตอบ

สาเหตุ: CPU-intensive operations (JSON.parse ข้อมูลใหญ่, crypto operations, image processing, complex regex) block event loop — ทำให้ทุก request ต้องรอจนกว่า operation จะเสร็จ

วิธีแก้:

  • ใช้ Worker Threads สำหรับ heavy computation: new Worker('./heavy-task.js')
  • ใช้ streaming แทน load ทั้งหมดเข้า memory: fs.createReadStream แทน fs.readFile สำหรับไฟล์ใหญ่
  • แยก CPU-intensive work ไป separate service/microservice
  • ใช้ node --prof หรือ clinic.js วิเคราะห์ bottleneck

CommonJS vs ESM import ปนกัน — ERR_REQUIRE_ESM

require() library แล้วได้ error ERR_REQUIRE_ESM

สาเหตุ: library เปลี่ยนเป็น ESM-only (เช่น node-fetch v3, chalk v5) แต่ project ยังใช้ CommonJS — require() ไม่สามารถ load ESM modules ได้

วิธีแก้:

  • ตั้ง "type": "module" ใน package.json แล้วใช้ import/export ทั้งหมด
  • ถ้ายังต้องใช้ CJS: ใช้ dynamic import const fetch = await import('node-fetch') หรือ pin version เก่าที่ยังเป็น CJS
  • ใช้ .mjs/.cjs extension เมื่อต้อง mix ทั้งสอง format ในโปรเจคเดียว

CORS errors กับ Express

Frontend เรียก API แล้วเจอ CORS error ใน browser console

สาเหตุ: ไม่ได้ install/configure cors middleware, หรือวาง middleware ผิดลำดับ (cors ต้องอยู่ก่อน route definitions), preflight OPTIONS request ไม่ถูก handle

วิธีแก้:

  • npm install cors แล้ว app.use(cors()) ก่อน route definitions ทุกตัว
  • config origin ให้ตรง: cors({ origin: 'https://myapp.com' }) สำหรับ production
  • ตรวจ response headers ใน browser DevTools → Network tab → ดู Access-Control-Allow-Origin

Environment variables เป็น undefined ใน production

process.env.DATABASE_URL เป็น undefined ทั้งที่ local ทำงานปกติ

สาเหตุ: .env file ไม่ถูก deploy ขึ้น server (ถูกต้องแล้วที่ไม่ deploy — อยู่ใน .gitignore), dotenv ไม่ถูก import ก่อนใช้ env vars, หรือตั้ง env vars ใน hosting platform ไม่ครบ

วิธีแก้:

  • validate env vars ตอน app startup — ถ้าขาดให้ fail fast พร้อมบอกว่าตัวไหนหาย
  • ใช้ validation library เช่น envalid หรือ zod validate env vars ให้ครบ
  • ตั้ง env vars ใน hosting platform (Vercel, Railway, Docker) — ไม่พึ่ง .env file ใน production
  • สร้าง .env.example เป็น checklist สำหรับ env vars ที่ต้องตั้ง

Related Skills

  • JavaScript — ภาษาที่ Node.js ใช้
  • TypeScript — type safety สำหรับ Node.js projects
  • Next.js — full-stack framework ที่ run บน Node.js
  • Docker — containerize Node.js applications