โหมดมืด
บทที่ 0 — Node.js คืออะไร และทำไมมันถึงเปลี่ยนโลก backend
💡 backend คืออะไร — ฝั่ง "หลังบ้าน" ของระบบที่ทำงานเบื้องหลัง (รันบน server ที่ไม่มีหน้าจอ) คอยจัดการข้อมูล, เปิด API ให้ frontend (เบราว์เซอร์/มือถือ) เรียกใช้, คุยกับ database — ตรงข้ามกับ frontend ที่เป็น "หน้าบ้าน" ที่ผู้ใช้เห็น
ก่อนพิมพ์โค้ดบรรทัดแรก เราจะตอบคำถาม 5 ข้อให้เคลียร์ก่อน — เพราะถ้าเข้าใจ "ภาพใหญ่" ผิดตั้งแต่ต้น ทั้งเล่มจะงง:
- Node.js ไม่ใช่ภาษา — แล้วมันคืออะไรกันแน่
- ทำไม JavaScript ถึงออกมาวิ่งนอกเบราว์เซอร์ได้ (ใครพามันออกมา)
- ข้างใน Node มีอะไร — V8 + libuv + event loop (3 คำนี้คืออะไร รวมทั้งคำว่า thread = เส้นทางการทำงาน 1 สาย ที่ทำได้ทีละอย่าง จะอธิบายเต็มในข้อ 3)
- ทำไม Node ใช้ thread เดียว แต่รับ request พร้อมกันเป็นหมื่นได้ (และเมื่อไหร่มันพัง)
- เขียน 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 กลับมาตอบ Amain thread ไม่เคยนั่งรอ — มันแค่ "สั่งงาน I/O แล้วไปต่อ" พอผลลัพธ์พร้อม ค่อยกลับมาทำงานที่ค้างไว้ กลไกที่คอย "หยิบงานที่พร้อมแล้วมาทำ" นี้คือ event loop
Event loop คืออะไร — อธิบายแบบพนักงานร้านกาแฟ
นึกภาพบาริสต้า คนเดียว ในร้านกาแฟ (= main thread):
- ลูกค้า A สั่งกาแฟ → บาริสต้ากดเครื่อง (= สั่ง I/O) → ไม่ยืนรอเครื่อง เดินไปรับออเดอร์ลูกค้า B ต่อ
- ลูกค้า B สั่ง → กดเครื่องอีกตัว → ไปรับ C ต่อ
- เครื่องของ A ส่งเสียง "ติ๊ง! เสร็จแล้ว" (= I/O เสร็จ → callback (ฟังก์ชันที่เราฝากไว้ให้เรียกตอนงานเสร็จ) เข้า queue (คิวรอ))
- บาริสต้าเห็นว่าว่าง → หยิบกาแฟ 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 / globalThis | global / globalThis |
| ข้อมูลเครื่อง/process | ❌ | ✅ process (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 มีfetchbuilt-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 22LTS คืออะไร และทำไมต้องเลือก: 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.x7. ลองใช้จริง — 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 — ลงมือก่อนไปบทถัดไป
- ติดตั้ง nvm + Node LTS แล้วยืนยันด้วย
node --version(ต้องเป็นเลขคู่ เช่น 20.x / 22.x) - เข้า REPL (
node) แล้วลองพิมพ์process.cwd(),process.env.HOME(หรือprocess.env.USERPROFILEบน Windows), และrequire("os").cpus()ดูว่าได้อะไร (REPL ใช้ CommonJS โดย default ใช้requireได้เลย) - สร้าง
hello.jsที่รับชื่อจาก argument แล้วทักทาย เช่นnode hello.js สมชาย→ พิมพ์สวัสดี สมชาย(ใบ้:process.argv[2]) - รัน
server.mjsแล้วลองเปลี่ยน URL ใน browser เป็น/about,/hello?x=1— ดูว่าreq.urlเปลี่ยนตาม - ทดลองจุดตาย: เพิ่มโค้ดบล็อก event loop ใน server (วน
while5 วินาทีก่อน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 ทำอะไรกันแน่
🔤 Glossary · 📋 Style guide · 📅 last_verified: 2026-06-03