1. ใช้โมดูลเป็น ESM แทน CommonJS
การประกาศโมดูลเปลี่ยนจาก module.exports และ require() เป็น export และ import แทนได้ ซึ่งสามารถรองรับ static analysis, tree-shaking และ alignment กับเบราว์เซอร์
เมื่อนำเข้า built-in module ให้ใส่ node: เสมอ เช่น node:fs หรือ node:http เพื่อแยกความชัดเจนระหว่าง native APIs กับแพ็กเกจ หรือไลบรารีภายนอก
ตัวอย่างโค้ด:
// math.js
export function add(a, b) { return a + b; }
// app.js
import { add } from ‘./math.js’;
import { readFile } from ‘node:fs/promises’;
ประโยชน์ คือ จะช่วยลดความสับสนเรื่อง dependency, ปรับปรุง tree-shaking, ทำให้โค้ดมีความสอดคล้องกับมาตรฐานเว็บ
.
2. ใช้ Top-Level await
เราสามารถใช้ await นอกฟังก์ชัน async ได้โดยตรงที่ระดับโมดูลแล้ว
โค้ดเดิม:
(async () => {
const cfg = await loadConfig();
startApp(cfg);
})();
ปัจจุบันใช้ clean initialization แบบนี้ได้:
const cfg = JSON.parse(await readFile(‘config.json’, ‘utf8’));
startApp(cfg);
ประโยชน์: โค้ดอ่านเข้าใจง่ายขึ้น, ลำดับการทำงานชัดเจน, ลด boilerplate
.
3. Node.js มี Web APIs ในตัว เราสามารถใช้ Fetch API ใช้ AbortController ได้เลย โดยไม่ต้องติดตั้ง axios หรือใช้ node-fetch อีกต่อไปได้
ตัวอย่างโค้ด เช่น :
try {
const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
const data = await res.json();
} catch (err) {
if (err.name === ‘TimeoutError’) { /* handle */ }
else { throw err; }
}
ประโยชน์: ลด dependency, error handling เป็นมาตรฐานเดียวกัน และรองรับการ cancellation ใน I/O ต่างๆ
.
4. มี Built-in Testing ในตัวแล้ว ไม่ต้องติดตั้งเพิ่มได้
ตัวอย่างโค้ด
import { test } from ‘node:test’;
import assert from ‘node:assert’;
test(‘add’, () => {
assert.strictEqual(add(1,2), 3);
});
ตัวอย่างคำสั่งในรัน test:
รันทั้งหมด:
node –test
Watch mode:
node –test –watch
Coverage (Node 20+):
node –test –experimental-test-coverage
ประโยชน์: ไม่ต้องติดตั้ง Jest/Mocha, ลด config, feedback เร็วด้วย watch mode
.
5. ใช้รูปแบบ Async/Await ขั้นสูงได้ เช่น
การใช้ Parallel Execution เช่น Promise.all() รันงานที่ไม่พึ่งกันแบบพร้อมกัน
หรือใช้ Structured Error Handling เก็บ context ใน catch block, log ข้อมูลเป็นโครงสร้าง
ตัวอย่างโค้ด:
try {
const [cfg, users] = await Promise.all([loadConfig(), fetchUsers()]);
// process…
} catch (err) {
console.error({ message: err.message, stack: err.stack, time: Date.now() });
}
ประโยชน์: ช่วยเร่งประสิทธิภาพ, รวม error handling ไว้จุดเดียว พร้อม context
.
6. Stream ตามมาตรฐานเว็บ
ใช้ pipeline() แบบ promise เพื่อจัดการ cleanup และ error อัตโนมัติ
ใช้ Transform Stream สำหรับ แยก logic ในแต่ละขั้นให้ชัดเจน (objectMode, transform)
ใช้ Web Streams เพื่อแปลงระหว่าง Node.js streams และ Web Streams ได้ด้วย Readable.fromWeb() และ toWeb()
ตัวอย่างโค้ด:
await pipeline(
createReadStream(‘in.txt’),
new Transform({ transform(chunk, _, cb){ cb(null, chunk.toString().toUpperCase()) }}),
createWriteStream(‘out.txt’)
);
ประโยชน์: ลด boilerplate, ปรับปรุง error handling, รองรับ cross-environment
.
7. ควรใช้ Worker Threads สำหรับงานหนักๆ แทนการเขียนแบบปกติ
ควรแยกงาน CPU-bound ไว้ใน worker เพื่อไม่บล็อก event loop หลัก
ประโยชน์: เพิ่ม parallelism, แอปยังตอบสนองได้ดีแม้มีงานหนัก
.
8. Modern Node.js ช่วยให้ประสบการณ์นักพัฒนา (DX) ดีขึ้น เช่น
ใช้ –watch แทน nodemon: สั่ง node –watch app.js ให้ reload อัตโนมัติ
ใช้ –env-file แทน dotenv: โหลด .env แบบ native ไม่ต้องติดตั้งแพ็กเกจภายนอกได้
ตัวอย่างไฟล์ package.json:
“scripts”: {
“dev”: “node –watch –env-file .env app.js”,
“test”: “node –test –watch”
}
ประโยชน์: ลด configuration, เริ่มงานได้เร็ว, โค้ดสะอาด
.
9. การ Distribution และ Deployment ที่ดีขึ้น
สามารถสร้าง Single Executable ได้ ใช้ SEA Config (–experimental-sea-config) สร้างไฟล์ bundle เดียว
Config ตัวอย่าง (sea-config.json):
{ “main”:”app.js”, “output”:”app.blob” }
ประโยชน์: ง่ายต่อการ deploy, ไม่ต้องติดตั้ง Node.js บนเครื่องปลายทาง
.
10. การจัดการแพ็กเกจและการ resolve โมดูล แบบ Modern
Import Maps ใช้ กำหนด alias ภายในโปรเจกต์ เช่น
{ “imports”: { “#utils/”:”./src/utils/” } }
หรือ Dynamic Imports: ใช้โหลดโมดูลแบบเงื่อนไขหรือ code-splitting ได้สะดวก
ตัวอย่าง:
if (featureEnabled) {
const mod = await import(‘#utils/logger’);
mod.log(‘Feature on’);
}
ประโยชน์: ชัดเจนในการอ้างอิง, refactor ง่าย, โหลดเฉพาะโค้ดที่ต้องใช้จริง
.
สรุป Node.js จะไม่ได้เป็นแค่ JavaScript runtime อีกต่อไปแล้ว แต่กลายเป็นแพลตฟอร์มพัฒนาเว็บเต็มรูปแบบ การนำแนวทางสมัยใหม่มาใช้งานช่วยให้โค้ดดูแลรักษาง่าย ประสิทธิภาพสูง และ Node.js รุ่นใหม่ยังคงรองรับโค้ดเดิม (backward compatibility) ทำให้เราสามารถปรับใช้ทีละน้อยควบคู่กับโปรเจกต์ปัจจุบันได้ ไม่ว่าจะเริ่มโปรเจกต์ใหม่หรือยกระดับระบบเก่า แนวทางเหล่านี้จะเป็นรากฐานที่มั่นคงสำหรับการพัฒนาแอปที่ทันสมัยและดูแลรักษาได้ง่ายในระยะยาวครับ