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
# 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 auditEvent 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)
- CommonJS —
require()/module.exports, synchronous, default ใน Node.js - ES Modules —
import/export, async, ใช้"type": "module"ใน package.json - โปรเจคใหม่แนะนำใช้ ESM เพราะเป็น standard ของ JavaScript
npm & package.json
package.json— define project metadata, scripts, dependenciespackage-lock.json— lock exact versions สำหรับ reproducible installsscripts— define custom commands เช่น"dev": "next dev","build": "tsc"dependenciesvsdevDependencies— 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-errorspackage หรือ 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/.cjsextension เมื่อต้อง 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หรือzodvalidate env vars ให้ครบ - ตั้ง env vars ใน hosting platform (Vercel, Railway, Docker) — ไม่พึ่ง
.envfile ใน 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