Core APIs
Core APIs ของ Node คืออะไร?
หัวข้อที่มีชื่อว่า “Core APIs ของ Node คืออะไร?”Node.js มาพร้อม globals และ modules ในตัวชุดใหญ่ที่ใช้งานได้ทันทีโดยไม่ต้องติดตั้งอะไรเพิ่ม สิ่งเหล่านี้คือ primitive ที่โปรแกรม Node.js ทุกตัวถูกสร้างขึ้นมาจากมัน
globals และ modules หลักที่โมดูลนี้ครอบคลุม:
process— เข้าถึง process ที่กำลังรันอยู่: environment variables, command-line arguments, working directory, platform และการควบคุม lifecycleBuffer— ก้อนข้อมูล binary ดิบที่มีความยาวคงที่ มีมาก่อน typed array และยังคงเป็นวิธีมาตรฐานในการจัดการ byte ใน stream และ networking ของ Nodenode:fs/node:fs/promises— อ่าน เขียน และนำทางในระบบไฟล์ promises API ทำให้ใช้async/awaitได้โดยตรงEventEmitter— แกนหลักของสถาปัตยกรรม event-driven ของ Node stream, HTTP server และไลบรารีของบุคคลที่สามจำนวนมากล้วน extendEventEmitter
โมดูลนี้ครอบคลุมอะไรบ้าง
หัวข้อที่มีชื่อว่า “โมดูลนี้ครอบคลุมอะไรบ้าง”| บทเรียน | หัวข้อ |
|---|---|
| process & env | process.argv, process.env, exit code และการตรวจจับ platform |
| Buffer | ข้อมูล binary, encodings และการจัดการระดับ byte |
| File System | fs callback, sync API และ interface ของ fs/promises |
| EventEmitter | custom event, listener และ lifecycle ของ once / removeListener |
Built-in ใหม่ ๆ ที่ควรรู้จัก
หัวข้อที่มีชื่อว่า “Built-in ใหม่ ๆ ที่ควรรู้จัก”Node ยังคงดูดซับ package ยอดนิยมเข้ามาไว้ใน runtime อย่างต่อเนื่อง:
node:sqlite— ฐานข้อมูล SQLite แบบฝังในตัว (ปลดธงมาตั้งแต่ 22.13 แต่ยัง Experimental บน Node 24 — การ import จะพิมพ์ExperimentalWarning) ไม่มี dependency สำหรับ local state, test และ CLIfs.glob(22+) — จับคู่ไฟล์โดยไม่ต้องใช้ packageglobnode:test— test runner ที่ครอบคลุมไปแล้วในโมดูลก่อนหน้า
import { DatabaseSync } from 'node:sqlite';
const db = new DatabaseSync(':memory:');db.exec('CREATE TABLE notes (id INTEGER PRIMARY KEY, body TEXT) STRICT');
const insert = db.prepare('INSERT INTO notes (body) VALUES (?)');insert.run('first');insert.run('second');
console.log(db.prepare('SELECT * FROM notes ORDER BY id').all());// [ { id: 1, body: 'first' }, { id: 2, body: 'second' } ]demo globals เบื้องต้น
หัวข้อที่มีชื่อว่า “demo globals เบื้องต้น”snippet ด้านล่างอ่าน globals สองตัวที่มีอยู่ในทุก Node.js process โดยไม่ต้อง require หรือ import เลย:
Output (verified on Node 24)
Node version: v24.13.0
String: Hello, Node!
Chars: 12
Bytes (UTF-8): 12Mental Model
หัวข้อที่มีชื่อว่า “Mental Model”สองตัวในนี้เป็น globals จริงที่เข้าถึงได้จากทุกที่โดยไม่ต้อง import เลย อีกสองตัวเป็น modules ที่ต้อง import เข้ามาอย่างชัดเจน — และหนึ่งในนั้น (EventEmitter) คือ base class ที่อีกสามตัวแอบพึ่งพาอยู่
flowchart TB
subgraph Globals["always available, no import"]
process["process"]
Buffer["Buffer"]
end
subgraph Modules["explicit import"]
fs["node:fs / node:fs/promises"]
events["node:events — EventEmitter"]
end
events -->|"extended by"| fsStream["fs.ReadStream / fs.WriteStream"]
fs -->|"returns"| fsStream
events -->|"extended by"| httpNet["http.Server, net.Socket (later modules)"]
process -->|"reports on"| httpNet Trade-offs
หัวข้อที่มีชื่อว่า “Trade-offs”| ทางเลือก | ข้อดี | ต้นทุน |
|---|---|---|
process / Buffer เป็น globals | เข้าถึงได้จากไฟล์ไหนก็ได้โดยไม่มี friction ไม่ต้องวุ่นวายกับ import | มองเห็น dependency ได้ยากขึ้นแค่ดูผ่าน ๆ — function ที่ใช้ process.env ไม่มีสัญญาณระดับ import บอกว่ามันอ่าน config |
prefix node: เป็นทางเลือกสำหรับ module รุ่นเก่า (fs, path) | code เก่า (require('fs')) ยังทำงานได้ตลอดไป | มีการสะกดสองแบบสำหรับ module เดียวกันอยู่ใน codebase — style ไม่สม่ำเสมอ |
prefix node: บังคับสำหรับ module ใหม่ (node:test, node:sqlite) | ไม่มีทางถูกบัง (shadow) ด้วย npm package ที่ชื่อ test หรือ sqlite | ไม่มี fallback แบบไม่มี prefix — copy-paste code สไตล์เก่าอย่าง require('sqlite') จะ fail ด้วย MODULE_NOT_FOUND แทนที่จะได้ error ที่ชัดเจนกว่า |
Common Misconceptions
หัวข้อที่มีชื่อว่า “Common Misconceptions”- “Node built-in ทุกตัวต้อง import” — ความจริง:
processและBufferเป็น globals; มีแค่ module อย่างnode:fsและnode:eventsเท่านั้นที่ต้องimport/require - “prefix
node:เป็นแค่การตกแต่ง” — ความจริง: สำหรับ module รุ่นเก่ามันเป็นแค่ style ที่เป็นทางเลือก; สำหรับnode:testและnode:sqliteมันคือ specifier ที่ ถูกต้องเพียงแบบเดียว — ไม่มีrequire('test')แบบเปล่า ๆ - “
node:sqliteพร้อมใช้งานจริงเพราะมันมาพร้อม Node 24” — ความจริง: มันยังพิมพ์ExperimentalWarningทุกครั้งที่ import บน 24.13; API ยังเปลี่ยนแปลงได้ใน semver-minor release
อ่านโค้ดที่ AI เขียน
หัวข้อที่มีชื่อว่า “อ่านโค้ดที่ AI เขียน”- code ที่ generate มา
require('sqlite')หรือrequire('test')โดยไม่มี prefixnode:หรือเปล่า? ทั้งคู่ throwMODULE_NOT_FOUND— สอง module นี้ไม่มีรูปแบบไม่มี prefix ต่างจากfsหรือpath - snippet ปฏิบัติต่อ
node:sqliteเหมือนว่ามันเสถียรแล้ว (ไม่มีการจัดการ warning ใช้แบบลวก ๆ ใน ตัวอย่าง) ทั้งที่มันยังเป็น Experimental บน Node version เป้าหมายหรือเปล่า? - code import
Bufferหรือprocessจากที่ไหนสักแห่ง (import { Buffer } from 'node:buffer') หรือเปล่า? แบบนี้ถูกต้องแต่ไม่จำเป็น — ตรวจดูให้ดีว่ามันไม่ได้ซ่อน typo อย่างbuferที่ linter น่าจะจับได้ถ้าใช้ global form
🐛 หา bug ในโค้ดนี้
const { test } = require('test');
test('adds numbers', () => {console.log('ok');});เฉลย
node:test ไม่มีรูปแบบไม่มี prefix — มีแค่ require('node:test') (หรือ import { test } from 'node:test') เท่านั้นที่ resolve ได้ การเขียน require('test') เฉย ๆ จะ throw Error [ERR_MODULE_NOT_FOUND] / MODULE_NOT_FOUND: Cannot find module 'test' เพราะ Node ไม่ได้ลงทะเบียน test แบบเปล่า ๆ ไว้เป็น module specifier — มีแค่ node:test เท่านั้น วิธีแก้คือ require('node:test') (หรือ import { test } from 'node:test') นี่คือกติกาเดียวกับ node:sqlite: built-in ใหม่เอี่ยมมีอยู่เฉพาะภายใต้ชื่อที่มี prefix เท่านั้น ต่างจาก module รุ่นเก่าอย่าง fs ที่สะกดได้ทั้งสองแบบ