23 คะแนน โดย GN⁺ 2025-08-04 | 3 ความคิดเห็น | แชร์ทาง WhatsApp
  • สภาพแวดล้อมการพัฒนา Node.js ในช่วงไม่กี่ปีที่ผ่านมาได้เกิดการเปลี่ยนแปลงครั้งใหญ่ ทั้งด้านความเข้ากันได้กับ มาตรฐานเว็บ และการเสริมความสามารถแบบ built-in
  • การนำระบบโมดูลและแพตเทิร์นอะซิงโครนัสสมัยใหม่มาใช้ เช่น ESM(ES Modules), คำนำหน้า node: และ Top-level await ทำให้เขียนโค้ดได้ตรงไปตรงมาและปลอดภัยยิ่งขึ้น
  • มีการรองรับฟังก์ชันจำนวนมากผ่าน API ที่มีมาในตัว เช่น Fetch API, AbortController และ Web Streams ทำให้ลดการพึ่งพาไลบรารีภายนอกแบบเดิม
  • เครื่องมือพัฒนาแบบ built-in เช่น test runner, โหมด Watch, การรองรับไฟล์ environment ช่วยเพิ่มความสะดวกและประสิทธิภาพในการทำงานอย่างมาก
  • มีการเสริม โครงสร้างพื้นฐานด้านความปลอดภัยและการดีพลอย ให้แข็งแกร่งขึ้น ตั้งแต่การควบคุมสิทธิ์, diagnostics channel ไปจนถึงการแจกจ่ายแบบไฟล์รันเดี่ยว ทำให้ Node.js ยุคใหม่กำลังพัฒนาเป็นแพลตฟอร์มที่ทั้งมืออาชีพและใช้งานได้รอบด้าน

การเปลี่ยนแปลงและพัฒนาการของ Node.js

  • Node.js กำลังเปลี่ยนผ่านจากโครงสร้างแบบ callback เป็นหลัก และยึด CommonJS เป็นศูนย์กลาง ในยุคเริ่มต้น ไปสู่ สภาพแวดล้อมการพัฒนาที่เป็นมาตรฐานมากขึ้น ในปัจจุบัน
  • การเปลี่ยนแปลงนี้ไม่ใช่แค่เรื่องรูปลักษณ์ภายนอก แต่เป็นการเปลี่ยนกระบวนทัศน์การพัฒนาโดยรวมของ JavaScript ฝั่งเซิร์ฟเวอร์

1. ระบบโมดูล: การทำให้ ES Modules เป็นมาตรฐาน

  • แม้ CommonJS จะเป็นรูปแบบที่ใช้กับ Node.js มาอย่างยาวนาน แต่ก็มีข้อจำกัดด้าน static analysis, tree shaking และปัญหาความไม่สอดคล้องกับมาตรฐานเว็บ
  • รูปแบบ ESM(ES Modules) ได้กลายเป็นมาตรฐานใหม่ของ Node.js แล้ว
    • ใช้ไวยากรณ์ import, export
    • มีการนำคำนำหน้า node: มาใช้เพื่อแยก built-in modules อย่างชัดเจน
      • ตัวอย่าง: import { readFile } from 'node:fs/promises'
      • ทำให้แยกความต่างระหว่าง built-in กับแพ็กเกจ npm ได้ชัดเจนขึ้น
  • การรองรับ Top-level await ทำให้สามารถใช้ await ได้ที่ระดับบนสุดของโมดูล
    • ไม่จำเป็นต้องครอบด้วย async function ที่รันทันทีอีกต่อไป
    • โค้ดจึงตรงไปตรงมาและเข้าใจง่ายขึ้น

2. Web API แบบ built-in: ลดการพึ่งพาภายนอก

  • Fetch API ถูกฝังมาใน Node.js แล้ว ทำให้ส่งคำขอ HTTP ได้โดยไม่ต้องพึ่ง dependency ภายนอกอย่าง Axios หรือ node-fetch
  • โดยพื้นฐานแล้ว Fetch รองรับ timeout และการยกเลิกคำสั่ง (AbortSignal.timeout())
    • จึงจัดการ error ได้อย่างสม่ำเสมอโดยไม่ต้องใช้ไลบรารี timeout แยกต่างหาก
  • ด้วย AbortController จึงสามารถทำแพตเทิร์นการยกเลิกสำหรับงานอะซิงโครนัสหลากหลายประเภท ทั้งไฟล์และเครือข่ายได้
    • มอบวิธีมาตรฐานสำหรับการจัดการการขัดจังหวะจากผู้ใช้หรือการหมดเวลา

3. การทดสอบแบบ built-in: สภาพแวดล้อมทดสอบระดับมืออาชีพ

  • โดยไม่ต้องใช้เฟรมเวิร์กภายนอกอย่าง Jest หรือ Mocha ก็สามารถตอบโจทย์ส่วนใหญ่ได้ด้วย test runner ที่มีมาใน Node.js
    • เขียนเทสต์ได้อย่างตรงไปตรงมาด้วย node:test และ node:assert
  • มีฟีเจอร์อำนวยความสะดวกในการพัฒนาแบบ built-in เช่น โหมด Watch ของการทดสอบ และ การรายงาน coverage
    • ทุกครั้งที่แก้โค้ด ระบบจะรันเทสต์ให้อัตโนมัติ
    • Node.js 20 ขึ้นไปรองรับฟีเจอร์ coverage แบบ experimental

4. แพตเทิร์นอะซิงโครนัสที่ก้าวหน้า

  • แม้ async/await จะถูกใช้อย่างแพร่หลาย แต่ Node.js ยุคใหม่เน้นการใช้แพตเทิร์นสำหรับการทำงานแบบขนานและการจัดการ error ที่ละเอียดขึ้น
    • ใช้ Promise.all() เพื่อทำงานหลายอย่างพร้อมกัน และจัดการ error ใน try/catch เดียวพร้อมข้อมูลบริบท
  • การใช้ AsyncIterator ช่วยให้จัดการอีเวนต์แบบลำดับต่อเนื่องและควบคุมโฟลว์ได้ง่ายขึ้น

5. ความสามารถด้านสตรีมขั้นสูงและความเข้ากันได้กับมาตรฐานเว็บ

  • API ของสตรีมมีความเข้ากันได้กับมาตรฐานเว็บ (Streams API) แล้ว
    • ด้วย Readable.fromWeb, Readable.toWeb จึงสามารถแปลงสตรีมระหว่าง Node.js กับเบราว์เซอร์ได้
  • ฟังก์ชัน pipeline (แบบ Promise-based) ช่วยให้สร้าง stream pipeline ได้อย่างตรงไปตรงมาและปลอดภัย

6. Worker Threads: การประมวลผลงานที่ใช้ CPU หนักแบบขนาน

  • ใช้ WorkerThreads เพื่อก้าวข้ามข้อจำกัดของ JS แบบ single-thread และใช้ประโยชน์จากหลายคอร์ได้
  • สามารถประมวลผลการคำนวณที่ซับซ้อนหรือข้อมูลขนาดใหญ่ได้โดยไม่บล็อกลูปหลัก

7. การปฏิวัติประสบการณ์นักพัฒนา

  • ใช้แฟลก --watch เพื่อตรวจจับการเปลี่ยนแปลงของโค้ดและรันใหม่อัตโนมัติได้โดยไม่ต้องใช้ nodemon
  • ใช้แฟลก --env-file แทน dotenv ได้ ทำให้ใช้ตัวแปรสภาพแวดล้อมได้ทันที
  • การตั้งค่าสภาพแวดล้อมพัฒนาจึงเรียบง่ายและรวดเร็วขึ้น

8. มีระบบความปลอดภัยและการมอนิเตอร์ประสิทธิภาพในตัว

  • ด้วย Permission Model แบบ experimental จึงสามารถจำกัดสิทธิ์ของแอปพลิเคชัน เช่น การเข้าถึงไฟล์หรือเครือข่ายได้
    • เหมาะต่อการใช้หลักสิทธิ์ขั้นต่ำและการทำตามข้อกำหนดด้านความปลอดภัย
  • ใช้ perf_hooks เพื่อวัดประสิทธิภาพในตัว และสามารถวิเคราะห์พร้อมบันทึกงานที่ทำงานช้าได้อัตโนมัติ

9. การดีพลอยและแพ็กเกจจิงที่ทันสมัยขึ้น

  • รองรับ SEA(Single Executable Application) ทำให้สามารถดีพลอย Node.js และแอปเป็นไบนารีไฟล์เดียวได้
    • จึงดีพลอยและติดตั้งได้สะดวกแม้ในสภาพแวดล้อมที่ไม่มี Node.js

10. การจัดการข้อผิดพลาดและการวินิจฉัยแบบสมัยใหม่

  • ใช้ structured error classes เพื่อแนบข้อมูลบริบทและข้อมูลวินิจฉัยที่สมบูรณ์ขึ้น พร้อมส่งต่อออบเจ็กต์ error อย่างสม่ำเสมอ
  • ใช้ diagnostics_channel เพื่อส่งข้อมูลวินิจฉัยแบบ event-driven ที่ปรับแต่งได้ และทำระบบมอนิเตอร์อัตโนมัติ

11. พัฒนาการของการตีความโมดูลและการจัดการแพ็กเกจ

  • ใช้ Import Maps เพื่อจัดการเส้นทางภายในผ่าน namespace แยกต่างหาก
    • ช่วยให้แยกโมดูลภายในและรีแฟกเตอร์ได้สะดวกขึ้น
  • ใช้ dynamic import เพื่อโหลดโค้ดระหว่างรันไทม์และทำ code splitting ตามสภาพแวดล้อมหรือการตั้งค่าได้

สรุปประเด็นสำคัญและมุมมองอนาคต

  • สำหรับ Node.js สิ่งสำคัญคือ การยึดตามมาตรฐานเว็บ, การใช้เครื่องมือ built-in ให้คุ้มค่าสูงสุด และ การเลือกใช้แพตเทิร์นอะซิงโครนัสสมัยใหม่
  • Node.js กำลังพัฒนาเป็นแพลตฟอร์มสำหรับมืออาชีพมากขึ้น ด้วยการประมวลผลแบบขนานประสิทธิภาพสูงอย่าง Worker Threads และ ความสามารถด้านการวินิจฉัย/ความปลอดภัย
  • ฟีเจอร์ใหม่อย่าง การดีพลอยแบบไฟล์รันเดี่ยว และ namespace ของโมดูล ช่วยเพิ่มความสะดวกในการปฏิบัติการอย่างมาก
  • แพตเทิร์นเหล่านี้สามารถนำมาใช้แบบค่อยเป็นค่อยไปได้ โดยยังคงเข้ากันได้กับโค้ดเดิม
  • หลังปี 2025 เป็นต้นไป Node.js จะยังคงพัฒนาอย่างต่อเนื่อง และแพตเทิร์นสมัยใหม่ที่แนะนำในที่นี้จะกลายเป็นรากฐานของแอปพลิเคชันที่มองไปข้างหน้า

3 ความคิดเห็น

 
sanori 2025-08-07

พอเริ่มสร้างโปรเจ็กต์ด้วย Deno ก็รู้สึกว่า 'ว้าว แบบนี้ก็ทำได้ด้วยเหรอ' แต่ดูเหมือนว่า node.js ก็กำลังเปลี่ยนไปในทิศทางคล้าย ๆ กันเหมือนกัน

 
dnltmdwhd 2025-08-05

โอ้ ตอนนี้ไม่ต้องใช้ axios แล้ว ใช้ fetch ได้ตรงๆ เลย

 
GN⁺ 2025-08-04
ความคิดเห็นใน Hacker News
  • การเปลี่ยนแปลงที่ใหญ่ที่สุดไม่ใช่ ESM แต่คือ Node มี fetch และ AbortController มาให้ในตัว ทำให้ตัด axios หรือ node-fetch ออกได้ ขนาดของ Lambda bundle ก็เล็กลง และลด cold start latency ได้อีกราว 100ms ถ้าเป็นคนที่ชอบพิมพ์ npm i axios จนติดเป็นนิสัย ก็ถึงเวลาหยุดได้แล้วใน Node รุ่นปี 2025
    • ชอบใช้ ts-rest ทั้งสแตกสำหรับทั้งการเรียก API และการตรวจสอบความถูกต้อง มันเป็นไลบรารีที่เบาที่สุดแต่ยังให้ type safety ที่แข็งแรงในบรรดาไลบรารีที่อิง zod/JSON Schema และยังเลือก HTTP client ที่ต้องการมาเสียบใช้ได้ด้วย (บน bun และเอนจิน node จะเลือก fastify) แม้จะมี overhead อยู่บ้าง แต่การย้าย type safety ไปอยู่ในขั้นคอมไพล์ก็คุ้มค่าพอ อยากรู้เหมือนกันว่ามีทางเลือกหรือความเห็นที่ดีกว่านี้ไหม เท่าที่หาได้ ts-rest เป็นตัวเดียวที่ได้ทั้งความเบาและ type safety
    • ไม่ค่อยชอบไวยากรณ์ของ fetch กับงานจัดการข้อยกเว้นเพิ่มเติมอย่าง await response.json เท่าไร ตอนใช้ axios มันตรงไปตรงมากว่ามาก ในโค้ดตัวอย่างก็เห็นได้ว่า axios แค่จัดการ response.data ได้เลย แต่ fetch ต้องเช็ก status เองก่อนแล้วค่อย parse JSON เลยจุกจิกกว่า
    • ในฐานะผู้เขียนไลบรารี การนำ ESM เข้ามากลับเป็นเรื่องที่ยากและเจ็บปวดกว่ามาก แต่ก็คุ้มค่ากับการอัปเกรด ส่วน fetch เองก็ยอดเยี่ยม แต่ ESM ทำให้ได้อะไรอีกเยอะมากจริง ๆ
    • node fetch ดีกว่า axios เพราะง่ายและเรียบกว่ามาก ยังไม่รู้เลยว่าทำไมบางคนถึงยังใช้ axios อยู่
    • ตื่นเต้นมากกับ Undici ซึ่งเป็นไลบรารี request ที่มีมาในตัว ดู เว็บไซต์ทางการของ undici
  • ตอนนี้รันแบบจำกัดสิทธิ์การเข้าถึงไฟล์ระบบหรือเครือข่ายได้แล้ว เช่นนี้
    # ตัวอย่างการจำกัดการเข้าถึงไฟล์ระบบ
    node --experimental-permission \
      --allow-fs-read=./data --allow-fs-write=./logs app.js
    
    # ตัวอย่างการจำกัดเครือข่าย
    node --experimental-permission \
      --allow-net=api.example.com app.js
    
    ดูเหมือนได้แรงบันดาลใจมาจาก Deno เป็นฟีเจอร์ที่ยอดเยี่ยมมาก ดู เอกสารฟีเจอร์ permission ของ Deno
  • ตอนนี้จัดสไตล์ข้อความได้เองแล้วโดยไม่ต้องติดตั้ง chalk หรือ picocolors
    const { styleText } = require('node:util');
    
    ดู เอกสารทางการของ styleText
  • ได้รู้หลายอย่างที่เอาไปใช้ได้ทันที
    1. Node มีตัวทดสอบในตัวแล้ว จึงไม่จำเป็นต้องใช้ jest เสมอไป
    2. Node มีฟีเจอร์ watch ในตัวแล้ว จึงไม่ต้องใช้ nodemon ด้วย
    • แต่ก็ยังชอบ jest มากกว่า เพราะใช้ jest-extended ได้
    • คิดว่าระบบทดสอบที่มีมาในตัวของ Node คุณภาพยังไม่ดี พอใช้จริงสักไม่กี่สัปดาห์ก็จะรู้เองว่าทำไม และต่อให้เปิด issue ไป ทีม Node ก็ไม่ได้สนใจนัก
  • ตามที่ Matteo Collina บอก node fetch ภายในใช้ fetch ของ undici แต่เพราะต้องสร้าง WHATWG web streams มันจึงช้ากว่าวิธี request ของ undici โดยธรรมชาติ
    วิดีโอ YouTube ที่พูดถึง,
    บล็อกอธิบายกลไกการทำงานของ undici
    • สำหรับคนที่สงสัย benchmark ดูได้ ที่นี่ ล่าสุดทดสอบทั้งบน local และ network บน MacBook Pro M3 Max แล้ว undici ดีที่สุดตอนรันแบบ local แต่บน network กลับได้ผลว่า Axios เร็วกว่า ไม่แน่ใจเหตุผลเหมือนกัน แต่ประสบการณ์ใช้ undici ตลอด 1 ปีครึ่งที่ผ่านมาเยี่ยมมาก ใช้ในโปรดักชันได้เสถียรพอแน่นอน เพียงแต่ถ้าจะเค้นประสิทธิภาพสูงสุด ก็ต้องคิดให้เหมาะกับสถานการณ์จริง
  • ด้วย native TypeScript transpiler ของ Node คนที่ใช้ TS จะลดความซับซ้อนได้มาก
    • จริง ๆ แล้วมันแค่ลบ type ออก ไม่ได้ transpile จริง ของอย่าง TS enum เลยทำงานไม่ได้
    • ตอนนี้ยังไม่พร้อมพอสำหรับใช้งานจริง ไม่ติดเรื่อง Enum แต่ยัง import ไฟล์โลคัลแบบไม่ใส่นามสกุลไม่ได้ และก็ยังประกาศ class property ใน constructor ไม่ได้
    • ตอนนี้ก็ไม่ต้องใช้แฟล็ก --experimental-strip-types แล้ว
  • หลายครั้งก็มักรู้จักฟีเจอร์ใหม่แบบบังเอิญประมาณนี้ มันให้ความรู้สึกคลุมเครือแบบ “อันนั้นมันของใหม่” คล้ายตอนใช้เบราว์เซอร์ สมัยก่อนตอนเขียนแต่ C# จะตื่นเต้นมากเวลาอ่านบทแนะนำฟีเจอร์ภาษาใหม่ ๆ แต่ทุกวันนี้ใช้หลายภาษาคู่กันอยู่ จะตามให้ทันแค่ภาษาเดียวก็ไม่ง่ายแล้ว เลยแทบจะเรียนรู้แบบสุ่มจากบล็อกหรือคนรอบตัว
    • สนใจข่าว Node (V8) มาก เลยอ่าน release note ทุก 2-3 เดือนเพื่อไล่ดูฟีเจอร์พวกนี้ บางทีก็อ่าน ECMA proposals ด้วย หวังมากว่า pipeline operator จะได้เข้าเสียที
  • พอห่างจาก ecosystem ของ Node ไปพักหนึ่งแล้วกลับมาดูใหม่ ก็พบว่ามีฟีเจอร์ใหม่ที่น่าสนใจเพิ่มขึ้นเยอะจริง ๆ มองว่าเป็นผลจาก Deno และ Bun ที่เข้ามาเขย่าตลาดจนทีมพัฒนา Node ต้องเร่งเครื่องขึ้น
  • Node กำลังค่อย ๆ กลายเป็นคู่แข่งที่น่ากลัวขึ้นเรื่อย ๆ ในสนามเดียวกับ Bun.js, Deno และอื่น ๆ การแข่งขันกันแบบนี้ส่งผลดีต่อพัฒนาการของ JS runtime
    • การเปลี่ยนแปลงช้าแต่ชัดเจนและน่ายินดี ถึงอย่างนั้นก็ยังคิดถึง shell function $ ของ Bun อยู่ดี การใช้ JS เป็นสคริปต์มันสะดวกมากจนไม่อยากติดตั้งสอง runtime ไว้บนเซิร์ฟเวอร์เดียวกัน
  • มองว่าฟีเจอร์ใหม่ของ Node ก็แบ่งได้สองแบบเหมือนเบราว์เซอร์
    1. เทคโนโลยีใหม่จริง ๆ
    2. เลเยอร์ “แต่งให้ดูดี” ที่ครอบอยู่บนความสามารถเดิม
      การดูว่าคนให้น้ำหนักกับฝั่งไหนมากกว่าก็น่าสนใจดี
    • สิ่งที่สำหรับบางคนเป็น “เลเยอร์แต่งให้ดูดี” สำหรับอีกบางคนก็อาจเป็นเรื่อง usability (ergonomics)