Skip to content

บทที่ 0 — Node.js คืออะไร และทำไมมันถึงเปลี่ยนโลก backend

สารบัญ Node.js | บทที่ 1: Modules + npm →

💡 backend คืออะไร — ฝั่ง "หลังบ้าน" ของระบบที่ทำงานเบื้องหลัง (รันบน server ที่ไม่มีหน้าจอ) คอยจัดการข้อมูล, เปิด API ให้ frontend (เบราว์เซอร์/มือถือ) เรียกใช้, คุยกับ database — ตรงข้ามกับ frontend ที่เป็น "หน้าบ้าน" ที่ผู้ใช้เห็น

ก่อนพิมพ์โค้ดบรรทัดแรก เราจะตอบคำถาม 5 ข้อให้เคลียร์ก่อน — เพราะถ้าเข้าใจ "ภาพใหญ่" ผิดตั้งแต่ต้น ทั้งเล่มจะงง:

  1. Node.js ไม่ใช่ภาษา — แล้วมันคืออะไรกันแน่
  2. ทำไม JavaScript ถึงออกมาวิ่งนอกเบราว์เซอร์ได้ (ใครพามันออกมา)
  3. ข้างใน Node มีอะไร — V8 + libuv + event loop (3 คำนี้คืออะไร รวมทั้งคำว่า thread = เส้นทางการทำงาน 1 สาย ที่ทำได้ทีละอย่าง จะอธิบายเต็มในข้อ 3)
  4. ทำไม Node ใช้ thread เดียว แต่รับ request พร้อมกันเป็นหมื่นได้ (และเมื่อไหร่มันพัง)
  5. เขียน Node ต่างจากเขียน JS ในเบราว์เซอร์ยังไง

1. Node.js ไม่ใช่ภาษา — มันคือ "runtime"

ประโยคแรกที่ต้องจำให้ขึ้นใจ:

JavaScript คือภาษา · Node.js คือที่ ๆ ภาษานั้นไปรัน

เปรียบเทียบให้เห็นภาพ: ภาษาไทยคือ "ภาษา" — แต่คุณจะพูดภาษาไทยที่ไหนก็ได้: ที่บ้าน, ที่ทำงาน, ในวิทยุ สถานที่แต่ละแห่งมีของให้ใช้ต่างกัน (ที่บ้านมีตู้เย็น ที่ทำงานมีเครื่องถ่ายเอกสาร) ภาษาเดียวกัน แต่สิ่งแวดล้อมต่างกัน ทำได้ไม่เหมือนกัน

JavaScript ก็เหมือนกัน — มันรันได้ใน 2 ที่หลัก:

Runtime = สภาพแวดล้อมที่รันโค้ด พร้อม "ของแถม" (API = Application Programming Interface — ชุดคำสั่ง/ฟังก์ชันที่ runtime หรือ library (= ชุดโค้ดสำเร็จรูปที่คนอื่นเขียนไว้ให้เราเรียกใช้ซ้ำ ไม่ต้องเขียนเอง) เปิดให้เราเรียกใช้) ที่ภาษาเปล่า ๆ ไม่มี — ในเบราว์เซอร์ของแถมคือ DOM (Document Object Model — โครงสร้างแบบต้นไม้ที่แทนหน้าเว็บใน memory ให้ JS สั่งเปลี่ยนได้) ใน Node ของแถมคือความสามารถระดับระบบปฏิบัติการ (อ่านไฟล์ เปิด network เข้าถึง process)

📌 ภาษา JavaScript เองถูกกำหนดโดยมาตรฐานชื่อ ECMAScript (อ่าน "เอคมาสคริปต์" — ECMAScript คือชื่อ "มาตรฐาน" ของภาษา ส่วน JavaScript คือชื่อ "ภาษา" ที่อิงมาตรฐานนี้ เลขปีต่อท้ายคือเวอร์ชันมาตรฐาน เช่น ES2015, ES2020) — for, const, Array, Promise พวกนี้เป็นของภาษา มีเหมือนกันทั้งสองที่ ส่วน document.querySelector (browser) หรือ fs.readFile (Node) เป็น API ของ runtime ไม่ใช่ของภาษา


2. เรื่องเล่า: JavaScript หนีออกจากกรงเบราว์เซอร์

ปี 1995 JavaScript ถูกสร้างใน 10 วันเพื่อทำให้หน้าเว็บกระพริบ ๆ ได้ — ติดอยู่ในเบราว์เซอร์อย่างเดียวเกือบ 14 ปี

ปี 2009 Ryan Dahl เอา V8 (เครื่องยนต์ JavaScript ของ Chrome ที่ Google เปิดให้ใช้ฟรี และเร็วมาก) มาประกอบกับโค้ดที่จัดการ I/O (อ่าน "ไอ-โอ" — input/output งานรับ-ส่งข้อมูลกับโลกภายนอก เช่น อ่าน-เขียนไฟล์, คุย network, คุย database) ระดับระบบ แล้วเรียกมันว่า Node.js — ครั้งแรกที่ JavaScript รันบน server ได้

ทำไมมันถึงดัง? เพราะตอนนั้น backend ส่วนใหญ่ทำงานแบบ "1 request = 1 thread แล้วนั่งรอ" — request ไหนต้องรออ่าน DB, thread นั้นก็ค้างรอเฉย ๆ เปลือง memory มีกี่ request พร้อมกัน ก็ต้องเปิด thread เท่านั้นตัว เครื่องรับไหวจำกัด

Node เสนอวิธีคิดใหม่: thread เดียว แต่ไม่นั่งรอ ระหว่างรอ DB ตอบ main thread ก็ไปรับ request อื่นต่อได้เลย พอ DB ตอบกลับมาค่อยย้อนกลับมาทำงานที่ค้างไว้ (เดี๋ยวอธิบายละเอียดข้อ 4)

ผลพลอยได้ที่ใหญ่ที่สุด: เขียนภาษาเดียวทั้ง frontend และ backend — ไม่ต้องสลับสมองระหว่าง JS (หน้าบ้าน) กับ Java/PHP (หลังบ้าน) อีกต่อไป


3. ข้างใน Node มีอะไร — เปิดฝาดูเครื่องยนต์

Node.js ประกอบจาก 3 ส่วนหลัก:

  • V8 — เครื่องยนต์ที่แปลโค้ด JavaScript เป็น machine code แล้วรัน (ตัวเดียวกับใน Chrome) หน้าที่: รันโลจิกของคุณให้เร็ว
  • libuv (อ่าน "ลิบ-ยู-วี" — library ภาษา C ที่เป็นหัวใจของ async I/O ใน Node) ให้ 2 อย่างสำคัญ: (ก) event loop — กลไกหัวใจที่ทำให้ Node ไม่ต้องนั่งรอ I/O · (ข) thread pool — กลุ่ม thread เบื้องหลัง (thread pool = บ่อ thread หลายสายไว้ทำงานพร้อมกัน, default 4 ตัว — ปรับด้วย env var UV_THREADPOOL_SIZE ได้) เอาไว้ทำงาน I/O ที่ระบบปฏิบัติการไม่มี async ให้ (เช่นอ่านไฟล์ในบางระบบ) — pool นี้ยังถูกใช้โดย crypto (เข้ารหัส เช่น bcrypt/argon2), dns.lookup, zlib ด้วย ดังนั้นถ้าทำ password hashing หนัก ๆ pool อาจตันและกระทบการอ่านไฟล์ในเวลาเดียวกัน
  • Node API — ตัวห่อ (fs, http, crypto, ...) ที่ให้โค้ด JS เรียกความสามารถของ V8 + libuv ได้สะดวก

ประเด็นที่ต้องจำ: โค้ด JavaScript ของคุณรันบน thread เดียว (เรียก "main thread" = สายงานหลัก สายเดียวที่รันโค้ดของคุณ) แต่ งาน I/O เบื้องหลังอาจใช้หลาย thread ผ่าน libuv — สองอย่างนี้คนละเรื่องกัน เดี๋ยวข้อต่อไปจะเชื่อมให้


4. หัวใจของ Node — Event Loop และ "ทำไม thread เดียวถึงไม่ตัน"

นี่คือแนวคิดที่สำคัญที่สุดของทั้งเล่ม อ่านช้า ๆ

ปัญหา: ถ้านั่งรอ I/O จะเกิดอะไรขึ้น

สมมติ API ของเราต้องอ่านข้อมูลจาก DB ซึ่งใช้เวลา 50ms ถ้าทำแบบ blocking (นั่งรอ):

text
แบบนั่งรอ (blocking) — server ที่มี 1 thread:

request A เข้ามา → อ่าน DB → 😴 นั่งรอ 50ms → ตอบ A

                request B เข้ามาตอนนี้ ต้องรอ A เสร็จก่อน! (queue)

ถ้ามี 100 request พร้อมกัน request สุดท้ายต้องรอ 100 × 50ms = 5 วินาที — แย่มาก

วิธีของ Node: ไม่นั่งรอ (non-blocking)

Node บอก libuv ว่า "ช่วยอ่าน DB ให้หน่อย เสร็จแล้วบอกฉันด้วยนะ" แล้ว main thread ก็ไปทำงานอื่นต่อทันที ไม่นั่งรอ:

text
แบบไม่นั่งรอ (non-blocking) — Node 1 thread:

request A เข้ามา → สั่ง libuv "อ่าน DB ให้ที" → ไปรับ request B ต่อเลย
request B เข้ามา → สั่ง libuv "อ่าน DB ให้ที" → ไปรับ request C ต่อเลย
   ...
   (50ms ผ่านไป DB ของ A ตอบกลับ)
libuv: "DB ของ A เสร็จแล้ว!" → main thread กลับมาตอบ A

main thread ไม่เคยนั่งรอ — มันแค่ "สั่งงาน I/O แล้วไปต่อ" พอผลลัพธ์พร้อม ค่อยกลับมาทำงานที่ค้างไว้ กลไกที่คอย "หยิบงานที่พร้อมแล้วมาทำ" นี้คือ event loop

Event loop คืออะไร — อธิบายแบบพนักงานร้านกาแฟ

นึกภาพบาริสต้า คนเดียว ในร้านกาแฟ (= main thread):

  1. ลูกค้า A สั่งกาแฟ → บาริสต้ากดเครื่อง (= สั่ง I/O) → ไม่ยืนรอเครื่อง เดินไปรับออเดอร์ลูกค้า B ต่อ
  2. ลูกค้า B สั่ง → กดเครื่องอีกตัว → ไปรับ C ต่อ
  3. เครื่องของ A ส่งเสียง "ติ๊ง! เสร็จแล้ว" (= I/O เสร็จ → callback (ฟังก์ชันที่เราฝากไว้ให้เรียกตอนงานเสร็จ) เข้า queue (คิวรอ))
  4. บาริสต้าเห็นว่าว่าง → หยิบกาแฟ A เสิร์ฟ (= event loop หยิบ callback มารัน)

บาริสต้าคนเดียวเสิร์ฟลูกค้าได้เยอะมาก ตราบใดที่งานแต่ละชิ้นคือ "กดปุ่มแล้วรอเครื่องทำ" (= I/O) ไม่ใช่ "ต้องบดเมล็ดด้วยมือ 5 นาที" (= งาน CPU หนัก)

จุดตายของ Node: งาน CPU หนัก จะ "บล็อก" บาริสต้า

ถ้าลูกค้าคนหนึ่งสั่งให้บาริสต้า บดเมล็ดด้วยมือ 5 นาที (= งานคำนวณหนักบน main thread) — บาริสต้าคนเดียวต้องยืนบดจนเสร็จ ลูกค้าคนอื่นทั้งร้านต้องรอ เพราะไม่มีใครรับออเดอร์

javascript
// ❌ โค้ดแบบนี้ "บล็อก" event loop — ระหว่าง 5 วินาทีนี้ Node รับ request อื่นไม่ได้เลย
function blockEveryone() {
  const end = Date.now() + 5000;
  while (Date.now() < end) {
    // วน CPU เปล่า ๆ 5 วินาที — main thread ติดอยู่ตรงนี้ ออกไปไหนไม่ได้
  }
}

นี่คือบทเรียนข้อใหญ่: Node เก่งงาน I/O-bound แต่ไม่เหมาะกับงาน CPU-bound

💡 -bound (อ่าน "เบาด์") = "ถูกจำกัดด้วย..." — บอกว่าคอขวดของงานอยู่ตรงไหน

  • I/O-bound = งานที่ส่วนใหญ่ "รอ I/O" (เสียเวลากับการรอ network/DB/ไฟล์)
  • CPU-bound = งานที่ส่วนใหญ่ "เผา CPU" (คำนวณหนัก เช่น เข้ารหัสภาพ, ML)

งาน CPU หนักต้องโยนไป worker thread หรือ process อื่น (บทที่ 10)

⚠️ Pitfall มือใหม่: เขียน loop คำนวณหนัก ๆ ใน request handler ตรง ๆ แล้วงงว่าทำไม server "ค้าง" ตอน load สูง — เพราะมันบล็อก event loop ทั้งตัว ไม่ใช่แค่ request เดียว


5. เขียน Node ต่างจากเขียน JS ในเบราว์เซอร์ยังไง

ภาษาเหมือนกัน แต่ "ของในมือ" ต่างกัน:

สิ่งที่มีเบราว์เซอร์Node.js
จัดการหน้าเว็บdocument, window, DOM❌ ไม่มี (ไม่มีหน้าเว็บให้จัด)
อ่าน/เขียนไฟล์❌ ไม่ได้ (อันตราย)fs
เปิด server / networkจำกัด (fetch ออกได้อย่างเดียว)http, net — เปิด server เองได้
ตัวแปร global*window / globalThisglobal / globalThis
ข้อมูลเครื่อง/processprocess (env, argv, pid)
ระบุ "ที่อยู่ไฟล์ปัจจุบัน"__dirname, import.meta.url
  • แถวนี้เปรียบเทียบ "ตัวแปร global" (คำทั่วไป แปลว่าตัวแปรที่เข้าถึงได้จากทุกที่) กับ global ที่เป็นชื่อ object จริงในภาษา Node — คนละความหมายกันคนละบริบท อย่าสับสน

ตัวอย่างที่ชัดที่สุด — โค้ดนี้รันในเบราว์เซอร์ได้ แต่ใน Node พัง:

javascript
// ในเบราว์เซอร์: ได้ — เด้ง popup
alert("hi");          // ❌ ReferenceError: alert is not defined ใน Node
document.title;       // ❌ ReferenceError: document is not defined ใน Node

กลับกัน โค้ดนี้รันใน Node ได้ แต่ในเบราว์เซอร์ พัง:

javascript
// ใน Node: ได้
process.version;                 // เช่น 'v22.1.0' — เวอร์ชัน Node
import { readFile } from "node:fs/promises";   // อ่านไฟล์ — เบราว์เซอร์ทำไม่ได้

💡 ของกลางที่มีทั้งสองที่: console.log, setTimeout, Promise, fetch (Node มี fetch built-in ตั้งแต่ v18 และเลิก experimental ตั้งแต่ v21), AbortSignal.timeout()/AbortSignal.any() (Node 20+), structuredClone, JSON, Array, Math — พวกนี้เป็นภาษา/มาตรฐานร่วม ใช้ได้ทั้งคู่


6. ลงมือ — ติดตั้ง Node แบบมืออาชีพ (ด้วย nvm)

อย่าดาวน์โหลด installer จากเว็บตรง ๆ เพราะโปรเจกต์จริงต้องสลับเวอร์ชัน Node ไปมาอยู่เสมอ (เช่น โปรเจกต์เก่าใช้ Node 18 ส่วนโปรเจกต์ใหม่ใช้ Node 22) วิธีที่ถูกคือใช้ nvm (Node Version Manager) แทน — ตัวจัดการที่ให้ติดตั้งหลายเวอร์ชันไว้ในเครื่องเดียวกันแล้วสลับไปมาได้ตามต้องการ

📦 terminal คืออะไร — ตั้งแต่ตรงนี้ไปจะให้ "พิมพ์คำสั่ง" ใน terminal (หรือ command line / command prompt) = หน้าต่างดำ ๆ ที่พิมพ์คำสั่งคุยกับเครื่องโดยตรง (บน Mac คือแอป "Terminal", บน Windows คือ "PowerShell" หรือ "Command Prompt") · ในตัวอย่างคำสั่ง เครื่องหมาย $ (Mac/Linux) หรือ > (Windows) ข้างหน้าคือ prompt ที่ terminal พิมพ์ให้เองเพื่อบอกว่า "เชิญพิมพ์คำสั่งได้" — ไม่ต้องพิมพ์ $/> ตามนะ พิมพ์เฉพาะส่วนที่อยู่หลังมัน

bash
# macOS / Linux: ติดตั้ง nvm — curl = เครื่องมือดาวน์โหลดในบรรทัดคำสั่ง (มากับ Mac/Linux อยู่แล้ว)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
# (ปิด-เปิด terminal ใหม่)

# Windows: ใช้ nvm-windows แทน → ดาวน์โหลดจาก github.com/coreybutler/nvm-windows
# หมายเหตุ: nvm-windows ใช้ syntax ต่าง ไม่มี --lts ให้พิมพ์ `nvm install lts` หรือระบุเวอร์ชันตรง ๆ เช่น `nvm install 22.11.0`
bash
# ติดตั้ง Node เวอร์ชัน LTS ล่าสุด (LTS = เสถียร ใช้ production ได้)
# macOS/Linux:
nvm install --lts
# Windows (nvm-windows):
# nvm install lts

# ดูว่ามีเวอร์ชันอะไรบ้าง / ใช้ตัวไหนอยู่
nvm ls

# สลับไปใช้เวอร์ชันที่ต้องการ
nvm use 22

LTS คืออะไร และทำไมต้องเลือก: Node ออกเวอร์ชันใหม่ทุก 6 เดือน — เลขคู่ (20, 22, 24) คือ LTS (Long Term Support) ดูแลยาว ~3 ปี เหมาะกับ production · เลขคี่ (21, 23) คือเวอร์ชันทดลองฟีเจอร์ใหม่ อายุสั้น โปรเจกต์จริงให้ใช้ LTS เสมอ

⚠️ 2026: อย่าใช้ Node 18 กับโปรเจกต์ใหม่ — Node 18 หมดอายุ (EOL) เมษายน 2025 ไม่มี security patch แล้ว · สถานะ Active LTS/Current เปลี่ยนทุกเดือนตุลาคม ให้ตรวจสอบเวอร์ชันล่าสุดที่ nodejs.org/en/about/previous-releases ก่อนเลือกใช้จริง — เลือกเวอร์ชันที่เป็น Active LTS เสมอสำหรับ production

เช็กว่าติดตั้งสำเร็จ:

bash
node --version    # ควรขึ้น เช่น v22.1.0
npm --version     # npm มากับ Node อยู่แล้ว เช่น 10.x.x

7. ลองใช้จริง — REPL, ไฟล์แรก, และ server แรก

(ก) REPL — สนามทดลองโต้ตอบทันที

พิมพ์ node เฉย ๆ ใน terminal จะเข้า REPL (Read-Eval-Print Loop — "อ่าน-ประเมินค่า-แสดงผล-วนซ้ำ"; Eval = evaluate = ประเมินค่า/รันโค้ดแล้วได้ผลลัพธ์) — พิมพ์โค้ดทีละบรรทัด เห็นผลทันที เหมือน Console ในเบราว์เซอร์:

text
$ node
Welcome to Node.js v22.1.0.
> 1 + 1
2
> const name = "Node"
undefined
> `Hello ${name}`
'Hello Node'
> process.platform        // ลองของที่มีแต่ใน Node
'darwin'                  // ⚠️ ผลลัพธ์ขึ้นกับเครื่องคุณ: 'darwin' = macOS, 'win32' = Windows, 'linux' = Linux — ถ้าคุณใช้ Windows จะเห็น 'win32' ไม่ใช่ 'darwin' และนั่นถูกต้องแล้ว
> .exit                   // ออกจาก REPL (หรือกด Ctrl+D)

REPL เหมาะกับ "ลองเร็ว ๆ ว่า function นี้คืนอะไร" — ไม่ต้องสร้างไฟล์

(ข) ไฟล์แรก — รันสคริปต์

สร้างไฟล์ hello.js:

javascript
// hello.js
// console.log = พิมพ์ออก stdout (terminal) เหมือนในเบราว์เซอร์
console.log("Hello from Node!");

// process = object พิเศษของ Node ที่บอกข้อมูล process ที่กำลังรันอยู่
console.log("Node version:", process.version);   // เวอร์ชัน Node
console.log("รันบน OS:", process.platform);      // 'darwin' / 'win32' / 'linux'

// process.argv = arguments ที่ส่งมาตอนรัน (เดี๋ยวบทที่ 2 ลงลึก)
console.log("arguments:", process.argv.slice(2));

รันด้วยคำสั่ง node <ชื่อไฟล์>:

bash
$ node hello.js
Hello from Node!
Node version: v22.1.0
รันบน OS: darwin
arguments: []

$ node hello.js สมชาย 42      # ลองส่ง argument (ชื่อ + อายุ)
arguments: [ 'สมชาย', '42' ]

(ค) server แรก — ของที่เบราว์เซอร์ทำไม่ได้

นี่คือสิ่งที่ทำให้ Node เป็น Node — เปิด HTTP server ด้วยโค้ดไม่กี่บรรทัด (บทที่ 5 จะเจาะลึก ตอนนี้แค่ให้เห็นว่ามันง่ายแค่ไหน):

📌 เกี่ยวกับ import ในตัวอย่างนี้ — Node มี 2 ระบบ module: CommonJS (require(...)) แบบเก่า กับ ESM (import ... from ...) แบบมาตรฐานสมัยใหม่ที่บทที่ 1 จะอธิบายเต็ม ตอนนี้แค่จำว่า import คือวิธีดึง module เข้ามาใช้ — ทำตามตัวอย่างก็พอ ยังไม่ต้องเข้าใจรายละเอียด

javascript
// server.mjs
// เรียกใช้ core module 'http' ที่มากับ Node (core module = โมดูลที่ติดมากับ Node อยู่แล้ว ไม่ต้องติดตั้งเพิ่ม — อธิบายเต็มบทที่ 2; ขึ้นต้น node: เพื่อให้ชัดว่าเป็น built-in)
import { createServer } from "node:http";

// createServer รับ callback ที่จะถูกเรียก "ทุกครั้งที่มี request เข้ามา"
const server = createServer((req, res) => {
  // req = ข้อมูล request ที่เข้ามา (url, method, headers)
  // res = ตัวที่เราใช้ "เขียนคำตอบ" กลับไป
  res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
  res.end(`สวัสดี! คุณเรียก ${req.method} ${req.url}`);
});

// บอก server ให้ "ฟัง" ที่ port 3000 — รอ request ที่เข้ามาที่ port นี้
server.listen(3000, () => {
  console.log("Server รันที่ http://localhost:3000");
});

📌 ไฟล์นี้ใช้ import (ESM — ECMAScript Modules, ระบบ module มาตรฐานของ JS) — เพื่อให้ Node รู้ว่าเป็น ESM มี 2 วิธี: (ก) ตั้งชื่อไฟล์เป็น .mjs (วิธีเร็วสุดสำหรับตอนนี้) หรือ (ข) ใช้ .js แล้วใส่ "type": "module" ใน package.json (วิธีที่โปรเจกต์จริงในปี 2026 ใช้กัน — บทที่ 1 อธิบายเต็ม) · ตอนนี้แค่ทำตาม ยังไม่ต้องเข้าใจ — ตั้งชื่อ server.mjs แล้วรัน node server.mjs ได้เลย

bash
$ node server.mjs
Server รันที่ http://localhost:3000
# เปิดเบราว์เซอร์ไป http://localhost:3000 → เห็นข้อความตอบกลับ
# กด Ctrl+C เพื่อหยุด server

สังเกต: server ไม่จบการทำงาน — มันค้างอยู่เพื่อ "รอ" request ตลอดเวลา นี่คือ event loop กำลังทำงาน (บาริสต้ายืนรอออเดอร์อยู่) ต่างจาก hello.js ที่รันเสร็จแล้วจบทันที


🛠️ Checkpoint 0 — ลงมือก่อนไปบทถัดไป

  1. ติดตั้ง nvm + Node LTS แล้วยืนยันด้วย node --version (ต้องเป็นเลขคู่ เช่น 20.x / 22.x)
  2. เข้า REPL (node) แล้วลองพิมพ์ process.cwd(), process.env.HOME (หรือ process.env.USERPROFILE บน Windows), และ require("os").cpus() ดูว่าได้อะไร (REPL ใช้ CommonJS โดย default ใช้ require ได้เลย)
  3. สร้าง hello.js ที่รับชื่อจาก argument แล้วทักทาย เช่น node hello.js สมชาย → พิมพ์ สวัสดี สมชาย (ใบ้: process.argv[2])
  4. รัน server.mjs แล้วลองเปลี่ยน URL ใน browser เป็น /about, /hello?x=1 — ดูว่า req.url เปลี่ยนตาม
  5. ทดลองจุดตาย: เพิ่มโค้ดบล็อก event loop ใน server (วน while 5 วินาทีก่อน res.end) แล้วเปิด 2 แท็บพร้อมกัน — สังเกตว่าแท็บที่สองต้องรอแท็บแรกเสร็จก่อน

เฉลยข้อ 3:

javascript
// hello.js
const name = process.argv[2] ?? "ไม่ทราบชื่อ";  // argv[0]=node, argv[1]=path ไฟล์, argv[2]=ตัวแรกที่เราส่ง
console.log(`สวัสดี ${name}`);

สรุปบทที่ 0

  • JavaScript = ภาษา · Node.js = runtime (ที่ ๆ ภาษาไปรัน พร้อม API ระดับระบบ)
  • Node เกิดปี 2009 จาก V8 (Chrome) + libuv — พา JS ออกมาทำ backend ได้
  • ข้างใน Node = V8 (รัน JS) + libuv (event loop + thread pool สำหรับ I/O)
  • Event loop ทำให้ thread เดียวรับงานพร้อมกันได้เยอะ เพราะ "ไม่นั่งรอ I/O" — แต่จะ ตันทันทีถ้าเจองาน CPU หนัก บน main thread
  • เขียน Node ต่างจาก browser: ไม่มี document/window แต่มี process/fs/http
  • ติดตั้งด้วย nvm + เลือก LTS (เลขคู่) เสมอ

บทต่อไปเราจะตอบคำถามที่ทุกโปรเจกต์ Node ต้องเจอวันแรก: require กับ import ต่างกันยังไง, package.json คืออะไร, npm install ทำอะไรกันแน่

→ บทที่ 1: Modules + npm


🔤 Glossary · 📋 Style guide · 📅 last_verified: 2026-06-03