1 คะแนน โดย GN⁺ 2025-01-25 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Bun 1.2 เป็นรีลีสใหญ่ที่มุ่งเป็นเครื่องมือพัฒนา JavaScript/TypeScript แบบ full-stack โดยขยายทั้ง ความเข้ากันได้กับ Node.js รวมถึง runtime, bundler, test runner และ package manager ไปพร้อมกัน
  • เสริมการตรวจสอบความเข้ากันได้ด้วยการรันชุดทดสอบของ Node.js ทุกครั้งที่มีการเปลี่ยนแปลง และเพิ่มการรองรับ node:http2, node:dgram, node:cluster, node:zlib, node:v8
  • API ในตัวใหม่ Bun.s3 และ Bun.sql ดึงการเข้าถึง object storage ที่เข้ากันได้กับ S3 และ Postgres เข้ามาไว้ใน runtime เพื่อลดการพึ่งพา client ภายนอก
  • package manager เปลี่ยน lockfile เริ่มต้นจากไบนารี bun.lockb เป็น bun.lock แบบ JSONC และเพิ่ม .npmrc, bun publish, bun patch, bun outdated, bun run --filter
  • มีการเปลี่ยนแปลง working directory ของ bun run, การจัดการความล้มเหลวของ Bun.build(), ค่าที่ server.stop() ส่งกลับ, bun -p และค่าเริ่มต้นของ sourcemap ดังนั้นโปรเจกต์เดิมควรตรวจสอบ ผลกระทบต่อการย้ายเวอร์ชัน

เสริมความเข้ากันได้กับ Node.js

  • Bun 1.2 เปลี่ยนกระบวนการปรับปรุงความเข้ากันได้ โดยรัน ชุดทดสอบของ Node.js ทุกครั้งที่มีการเปลี่ยนแปลงใน Bun
    • ก่อนหน้านี้การแก้บั๊กเน้นอิงจาก GitHub issue หรือรายงานว่าแพ็กเกจ npm รันล้มเหลว แต่แนวทางนี้ใกล้เคียงกับการ “ไล่ตีตัวตุ่น” ซึ่งทำให้การรีแฟกเตอร์ครั้งใหญ่ทำได้ยาก
    • ได้พอร์ตไฟล์ทดสอบหลายพันไฟล์จาก repository ของ Node.js มาใช้กับ Bun และรันทดสอบเหล่านี้ทุก commit เพื่อตรวจสอบความเข้ากันได้
  • การทดสอบของ Node.js บางกรณีตรวจสอบรายละเอียดการทำงานภายในและข้อความ error ที่ตรงกันเป๊ะ ๆ ดังนั้นในบาง test Bun จึงเปลี่ยน internal binding เป็น stub ของตนเอง หรือปรับให้ตรวจสอบโดยเน้น name และ code
    • Bun พยายามทำให้ข้อความ error ตรงกับ Node.js ให้มากที่สุด แต่หาก name และ code เหมือนกัน ก็อาจให้ข้อความที่เป็นประโยชน์กว่าได้ในบางกรณี
  • โมดูลและฟีเจอร์ของ Node.js ที่รองรับใหม่
    • node:http2: รองรับการสร้างเซิร์ฟเวอร์ HTTP/2 และจำเป็นสำหรับเซิร์ฟเวอร์ gRPC ด้วย
    • node:dgram: รองรับ bind/connect ของ UDP socket
    • node:cluster: สามารถรัน Bun หลาย instance เพื่อกระจายงานไปยัง CPU หลายคอร์
    • node:zlib: เขียน implementation จาก JavaScript ใหม่เป็น native code และเร็วกว่า Bun 1.1 ถึง 2 เท่า
    • node:v8: ใช้ getHeapSnapshot, writeHeapSnapshot เพื่อตรวจสอบ heap ของ Bun ใน Chrome DevTools ได้
  • เซิร์ฟเวอร์ node:http2 ใน Bun 1.2 เร็วกว่า 2 เท่า เมื่อเทียบกับ Node.js
  • express ประมวลผล HTTP request ได้เร็วกว่า Node.js สูงสุด 3 เท่า จากการปรับปรุงความเข้ากันได้ของ node:http และการปรับแต่งเซิร์ฟเวอร์ HTTP ของ Bun
  • เพิ่มการรองรับ C++ addon ที่ใช้ V8 C++ API ด้วย
    • Node.js ใช้ V8 ส่วน Bun ใช้ JavaScriptCore ทำให้การ implement มีความยากสูง
    • Bun implement public C++ API ของ V8 บน JavaScriptCore เพื่อให้แพ็กเกจอย่าง cpu-features ทำงานได้
    • การรองรับ V8 C++ API มีความซับซ้อน จึงอาจยังมีฟีเจอร์ที่ขาดอยู่ในแพ็กเกจส่วนใหญ่ และยังคงปรับปรุงการรองรับแพ็กเกจอย่าง node-canvas@v2 และ node-sqlite3 ต่อไป

S3 API ในตัว Bun.s3

  • Bun 1.2 เพิ่ม Bun.s3 ซึ่งเป็น API ในตัว สำหรับจัดการ object storage ที่เข้ากันได้กับ S3
    • ใช้ได้กับบริการที่ implement S3 API เช่น Amazon S3, Google Cloud Storage, Cloudflare R2
    • จัดการการอ่าน เขียน และลบไฟล์ด้วย API ที่เข้ากันได้กับ Web standard Blob
  • s3.file() ส่งคืน lazy reference ไปยังไฟล์ S3 และใช้งานได้แบบเดียวกับ Bun File API เช่น text(), json(), arrayBuffer(), stream()
  • S3 client ของ Bun เขียนด้วย native code ไม่ใช่ JavaScript
    • เมื่อเทียบกับการใช้ @aws-sdk/client-s3 บน Node.js การดาวน์โหลดไฟล์จาก S3 bucket เร็วกว่า 5 เท่า
  • ฟีเจอร์เขียนข้อมูลมี write() และ writer()
    • write() อัปโหลด string, Uint8Array, Blob, Response ฯลฯ ได้
    • writer() ทำ multipart upload สำหรับไฟล์ขนาดใหญ่
  • presign() สร้าง presigned URL ที่อนุญาตให้อัปโหลดไฟล์เฉพาะรายการได้
    • ทำให้ผู้ใช้อัปโหลดไปยัง S3 ได้โดยตรงโดยไม่เปิดเผย credential หรือให้สิทธิ์เข้าถึง bucket เกินจำเป็น
  • เมื่อใช้ร่วมกับ Bun.serve() การใช้ new Response(s3.file(...)) จะ redirect ไปยัง presigned URL แทนที่เซิร์ฟเวอร์จะดาวน์โหลดไฟล์จาก S3 แล้วส่งต่ออีกครั้ง
    • ลดการใช้หน่วยความจำ เวลา และค่า bandwidth ที่เซิร์ฟเวอร์ต้องใช้ในการดาวน์โหลดไฟล์
  • URL แบบ s3:// ใช้ได้กับ Bun.file() และ fetch() ด้วย
    • อัปโหลด ดาวน์โหลด และลบได้ด้วย fetch("s3://...")
    • S3Client เริ่มต้นตั้งค่าผ่าน environment variables เช่น AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY

Postgres client ในตัว Bun.sql

  • Bun 1.2 เพิ่ม Bun.sql ซึ่งเป็น SQL client ในตัวที่รองรับ Postgres
    • ก่อนหน้านี้ Bun มี SQLite client ในตัวอยู่แล้ว และรีลีสนี้ขยายขอบเขตการรองรับฐานข้อมูล SQL
    • มี pull request สำหรับเพิ่มการรองรับ MySQL ด้วย
  • Bun.sql รัน SQL ด้วย tagged-template literal
    • ส่งค่า JavaScript เป็น SQL parameter ได้
    • ใช้การ escape string และ prepared statement โดยอัตโนมัติเพื่อป้องกัน SQL injection
  • ผลลัพธ์ส่งกลับเป็น array ของ object ที่ใช้ชื่อคอลัมน์เป็น key
  • ใช้ implementation แบบ native code และการปรับแต่งหลายอย่าง
    • prepared statement อัตโนมัติ
    • query pipelining
    • binary wire protocol
    • connection pooling
    • structure caching
  • อ่าน row ได้เร็วขึ้นสูงสุด 50% เมื่อเทียบกับการใช้ Postgres client ยอดนิยมบน Node.js
  • API ได้แรงบันดาลใจจาก postgres.js และออกแบบมาให้ย้ายโค้ดเดิมมาใช้ SQL client ในตัวของ Bun ได้ง่าย

การเปลี่ยนแปลงของตัวจัดการแพ็กเกจ

  • Bun 1.2 เปลี่ยน lockfile เริ่มต้นจากไบนารี bun.lockb เป็นแบบข้อความ bun.lock
    • bun.lockb เคยช่วยให้ bun install เร็วกว่า npm เกือบ 30 เท่า แต่ดูเนื้อหาบน GitHub ได้ยาก และทำให้การรีวิว pull request กับการแก้ merge conflict ทำได้ลำบาก
    • เครื่องมืออย่าง Dependabot ก็อ่าน lockfile ได้ยากเช่นกัน
  • bun.lock เป็นไฟล์ JSONC
    • รองรับคอมเมนต์และ trailing comma
    • ตรวจดู diff ใน pull request ได้ง่ายขึ้น และ trailing comma ช่วยลดโอกาสเกิด merge conflict
  • โปรเจกต์ใหม่จะสร้าง bun.lock
    • โปรเจกต์เดิมที่ใช้ bun.lockb จะยังรองรับ lockfile แบบไบนารีต่อไปโดยไม่มีการไมเกรตอัตโนมัติ
    • bun.lockb จะได้รับการรองรับระยะยาว และ bun add, bun update ก็ยังอัปเดตไฟล์นี้ต่อไป
    • สามารถไมเกรตเป็น lockfile แบบข้อความใหม่ได้ด้วย bun install --save-text-lockfile
  • bun install หลังเปลี่ยนมาใช้ lockfile แบบข้อความยัง เร็วกว่า Bun 1.1 อยู่ 30%
  • สามารถใช้คอมเมนต์และ trailing comma ใน package.json ได้
    • require() และ import() ก็อ่าน package.json แบบนี้ได้เช่นกัน
    • เนื่องจากยังไม่ใช่ฟีเจอร์ที่รองรับอย่างแพร่หลายในอีโคซิสเต็ม JavaScript ทั้งหมด จึงแนะนำให้ใช้แบบ “at your own risk”
  • เพิ่มการรองรับ .npmrc
    • อ่าน .npmrc ในรูทของโปรเจกต์และโฮมไดเรกทอรี
    • ใช้ตั้งค่า registry, scoped package และการยืนยันตัวตนสำหรับ private registry ได้
  • คำสั่งและตัวเลือกใหม่ของตัวจัดการแพ็กเกจ
    • bun run --filter: รันสคริปต์เดียวกันพร้อมกันในหลาย workspace
    • bun outdated: ตรวจสอบ dependency ที่ล้าสมัย
    • bun publish: ทางเลือกแทน npm publish รองรับการยืนยันตัวตนผ่าน .npmrc, การแพ็ก tarball, OTP และการจัดการ edge case ของ package.json
    • bun patch: บันทึกการแก้ไข dependency เป็นไฟล์ .patch ใน patches/ และนำไปใช้โดยอัตโนมัติเมื่อรัน bun install
    • --omit=dev|optional|peer: ไม่ติดตั้ง dependency ประเภท dev, optional, peer
    • ตั้งค่าใบรับรอง CA ได้จาก bunfig.toml, แฟล็ก CLI และ .npmrc
    • รองรับ bundleDependencies และการคงรูปแบบการย่อหน้าใน package.json ของ bun add ด้วย

การปรับปรุง test runner

  • bun test รองรับ JUnit XML reporter
    • ส่งผลการทดสอบไปยังเครื่องมือ CI/CD เช่น Jenkins, CircleCI, GitLab CI ได้ด้วย bun test --reporter=junit --reporter-outfile=junit.xml
    • ตั้งค่า JUnit reporting ใน bunfig.toml ได้เช่นกัน
  • เพิ่ม reporter แบบ LCOV สำหรับ code coverage
    • สร้าง coverage/lcov.info ได้ด้วย bun test --coverage --coverage-reporter=lcov
    • เปลี่ยนไดเรกทอรีเอาต์พุตได้ด้วย --coverage-dir
  • รองรับ inline snapshot ผ่าน expect().toMatchInlineSnapshot()
    • อัปเดต snapshot ภายในไฟล์ทดสอบด้วย bun test -u หรือ --update-snapshots
    • ใช้ toThrowErrorMatchingSnapshot() และ toThrowErrorMatchingInlineSnapshot() ได้ด้วย
  • test.only() ทำงานได้แล้วแม้ไม่มีแฟล็ก --only
  • API expect() เพิ่ม matcher แบบเดียวกับ Jest, Vitest และ jest-extended
    • กลุ่ม toContainValue(), toContainKey(), toHaveReturned()
    • ส่งข้อความ error แบบกำหนดเองเป็นอาร์กิวเมนต์ตัวที่สองได้
  • ใช้ jest.setTimeout() และ setDefaultTimeout() เพื่อเปลี่ยน timeout เริ่มต้นของการทดสอบใน scope หรือ module ปัจจุบันได้

ฟีเจอร์ bundler และ build

  • Bun 1.2 รองรับ HTML import
    • เมื่อนำไฟล์ HTML ส่งให้ตัวเลือก static ของ Bun.serve ระบบจะ bundle <script> และ <link> ใน HTML โดยอัตโนมัติและเปิดเป็น static route
  • bun build --compile รองรับ cross compilation
    • สร้างไบนารี Windows หรือ macOS จาก Linux ได้ และทำในทางกลับกันได้ด้วย
    • ใน build สำหรับ Windows สามารถตั้งค่าไอคอนและใช้ตัวเลือกซ่อนหน้าต่างคอนโซลได้
  • bun build --bytecode สร้าง bytecode cache
    • ทำให้เวลาเริ่มต้นของแอปพลิเคชันอย่าง eslint เร็วขึ้นได้ 2 เท่า
    • ไฟล์ .jsc เก็บ bytecode cache ของไฟล์ .js ที่เกี่ยวข้อง และต้องมีทั้งสองไฟล์จึงจะรันได้
    • bytecode cache อาจมีขนาดใหญ่กว่าซอร์สโค้ด 8 เท่า จึงแลกการลดเวลาเริ่มต้นกับการใช้พื้นที่ดิสก์มากขึ้น
  • ระบุรูปแบบเอาต์พุตเป็น CommonJS ได้ด้วย bun build --format=cjs
    • ก่อนหน้านี้รองรับเฉพาะ ESM
    • ทำให้สร้างไลบรารีหรือแอปพลิเคชันสำหรับ Node.js เวอร์ชันเก่าได้ง่ายขึ้น
  • ปรับปรุงการตรวจจับ CommonJS
    • เมื่อไฟล์มีความกำกวม จะใช้ directive "use strict" ด้านบนเป็น heuristic สุดท้ายของ CommonJS
    • require.main === module จะถูกเขียนใหม่เป็น import.meta.main เพื่อให้ใช้ร่วมกับคำสั่ง import ได้
  • Plugin API เพิ่ม hook onBeforeParse()
    • ต้อง implement ด้วย N-API addon ไม่ใช่ JavaScript
    • จัดการซอร์สโค้ดก่อนการ parse ได้แทบไม่มี overhead ในภาษา compiled เช่น Rust, C/C++, Zig
    • เป็น API ขั้นสูงสำหรับผู้เขียน plugin และ framework
  • ขยายตัวเลือก build ด้วย
    • inject environment variable เข้า bundle ด้วย --env="PUBLIC_*"
    • ลบการเรียกฟังก์ชันด้วยวิธีอย่าง --drop=console
    • เพิ่ม banner/footer
    • ตรวจดูรายการไฟล์ที่รวมอยู่ใน standalone executable ได้ด้วย Bun.embeddedFiles()
    • เมิน dead-code elimination annotation ที่ไม่ถูกต้องด้วย --ignore-dce-annotations
    • ตั้งค่าไม่ให้รวม dependency ของแพ็กเกจเข้า bundle ด้วย --packages=external

การ bundle CSS

  • Bun 1.2 implement CSS parser และ bundler ใหม่
    • สืบทอดจากงานของ LightningCSS และเขียนใหม่จาก Rust เป็น Zig เพื่อผสานกับ JavaScript/TypeScript parser, bundler และ runtime ของ Bun
  • ใช้ bun build ./index.css เพื่อรวมไฟล์ CSS หลายไฟล์ รวมถึงการอ้างอิง @import, url, @font-face เป็นไฟล์ CSS เดียวได้
  • import ไฟล์ .css จากโค้ด JavaScript และ TypeScript ได้
    • CSS ที่ import จาก JavaScript module graph และกฎ @import จะถูก flatten เป็นไฟล์ CSS เดียวต่อ entrypoint
  • ใช้ API Bun.build() เพื่อ bundle CSS และ JavaScript ผ่าน API เดียวกันได้

เพิ่ม API ของ Bun runtime

  • Bun.serve() รองรับ static route ผ่านพร็อพเพอร์ตี static
    • ส่ง path เป็น key และอ็อบเจ็กต์ Response เป็น value
    • static route เร็วกว่าการจัดการโดยตรงใน handler ของ fetch() ได้สูงสุด 40%
    • response body, header และ status code ถูก cache ไว้ในหน่วยความจำ จึงไม่มี JavaScript allocation และ garbage collection
    • สามารถ reload static route ได้ด้วย server.reload()
  • Bun.udpSocket() ให้ UDP socket ในรูปแบบ Bun API
    • แม้จะรองรับ node:dgram ด้วย แต่ Bun.udpSocket() เป็น API สมัยใหม่ที่คล้ายกับ Bun.listen() เดิม
    • สามารถส่ง UDP datagram หลายรายการด้วย syscall เดียว และรับมือกับ OS backpressure ได้
  • Bun.file() รองรับ delete(), unlink(), stat()
    • stat() คืนค่า metadata ในรูปแบบเดียวกับอ็อบเจ็กต์ Stats ของ Node.js fs.stat()
    • ใช้ API เดียวกันกับไฟล์ S3 ได้ด้วย
  • Bun.color() ให้การ parse, normalize และแปลงค่าสี
    • รองรับ CSS, ANSI color code, RGB, HSL เป็นต้น
  • dns.prefetch() สามารถดึง DNS record ไว้ล่วงหน้าเพื่ออุ่น DNS cache ตอนเริ่มต้นได้
  • utilities อื่น ๆ
    • Bun.inspect.table(): คืนค่าสตริงรูปแบบตารางเหมือน console.table
    • Bun.randomUUIDv7(): สร้าง monotonic UUID v7 ที่เหมาะกับการเรียงลำดับและฐานข้อมูล

ปรับปรุง SQLite client

  • SQLite client ในตัวของ Bun สามารถ map ผลลัพธ์ query เป็น class instance ได้ด้วย query.as(Class)
    • เพิ่ม getter, setter และ method ได้
    • ด้วยเหตุผลด้านประสิทธิภาพ จึงไม่รองรับ class constructor, default initializer และ private field
    • ไม่ใช่ ORM เพราะไม่ได้จัดการ relation หรือสร้าง SQL ให้
  • query.iterate() ประมวลผลแถวด้วย iterator โดยไม่โหลดทุกแถวขึ้นหน่วยความจำพร้อมกัน
    • ตัวอ็อบเจ็กต์ query เองก็วนด้วยลูป for ได้
  • เมื่อเปิดตัวเลือก strict สามารถละ prefix $, @, : ใน query parameter ได้
    • หาก parameter ขาดหายไป จะ throw error
  • ตรวจสอบจำนวนแถวที่เปลี่ยนแปลงและ row ID ล่าสุดที่ insert ได้จากผลลัพธ์ของ db.run()
    • changes
    • lastInsertRowid
  • ตัวเลือก safeIntegers คืนค่าจำนวนเต็ม 64 บิตเป็น BigInt แทน number ที่ถูกตัดทอน
    • ตั้งค่าได้ทั้งระดับ database หรือระดับ query
  • สามารถใช้ syntax using ของ JavaScript เพื่อ close statement และ database โดยอัตโนมัติเมื่อจบ scope

คอมไพล์และรัน C จาก JavaScript

  • Bun 1.2 เพิ่ม การรองรับแบบทดลอง สำหรับคอมไพล์และรัน C จาก JavaScript
    • ใช้ API cc() ของ bun:ffi
    • เป็นวิธีใช้ C system library จาก JavaScript โดยไม่ต้องมี build step แยกต่างหาก
  • Bun มี tinycc ในตัว
    • ต่างจาก gcc หรือ clang ตรงที่สามารถคอมไพล์โค้ด C ง่าย ๆ ได้ในระดับมิลลิวินาที
    • สามารถคอมไพล์และรันโค้ด C เมื่อจำเป็นได้
  • รองรับโค้ด C ที่ใช้ N-API ด้วย
    • ทำงานได้ด้วย Bun เพียงอย่างเดียว โดยไม่ต้องมีขั้นตอน build ของ node-gyp

รองรับ musl และ Alpine Linux

  • Bun 1.2 เพิ่ม build ของ Bun สำหรับ Linux distribution ที่ใช้ musl libc แทน glibc
    • ใช้ได้ในสภาพแวดล้อมอย่าง Alpine Linux
    • รองรับ Linux x64 และ aarch64
  • บน Docker สามารถใช้ image oven/bun:alpine ได้
  • musl ช่วยให้ container image มีขนาดเล็กลง แต่มีแนวโน้มว่าจะช้ากว่า Bun เวอร์ชัน glibc เล็กน้อย
    • หากไม่มีเหตุผลเฉพาะ แนะนำให้ใช้ glibc

ฟีเจอร์ภาษา JavaScript

  • เพิ่มการรองรับ import attributes
    • สามารถระบุ JSON, text, TOML ฯลฯ ตอน import ได้ เช่น import json from "./package.json" with { type: "json" }
    • ใช้กับ import() แบบ dynamic ได้ด้วย
  • รองรับ using และ await using
    • เมื่อออกจาก scope จะเรียก [Symbol.dispose] หรือ [Symbol.asyncDispose] เพื่อจัดการ resource โดยอัตโนมัติ
    • รองรับใน Bun API หลายตัว เช่น Bun.spawn(), Bun.serve(), Bun.connect(), Bun.listen(), bun:sqlite
  • API ใหม่เกี่ยวกับ Promise
    • Promise.withResolvers(): สร้าง promise, resolve, reject พร้อมกัน
    • Promise.try(): ห่อฟังก์ชันแบบ synchronous หรือ asynchronous ให้เป็น promise
  • API สำหรับ error และ byte array
    • Error.isError(): ตรวจสอบว่าเป็น Error ได้แม่นยำขึ้น แม้ในกรณีที่มีการแก้ prototype chain หรือสถานการณ์ cross-realm ของ node:vm
    • Uint8Array.toBase64() / Uint8Array.fromBase64()
    • Uint8Array.toHex() / Uint8Array.fromHex()
  • เพิ่ม iterator helper
    • map, flatMap, filter, take, drop, reduce, toArray, forEach, find
  • รองรับ Float16Array
    • array ของ floating point 16 บิตมีความแม่นยำน้อยกว่า 32 บิต แต่ใช้หน่วยความจำมีประสิทธิภาพกว่า

เพิ่ม Web API

  • รองรับ TextDecoderStream และ TextEncoderStream
    • เป็นเวอร์ชัน streaming ของ TextDecoder และ TextEncoder
    • ใน Bun, TextEncoderStream เร็วกว่า Node.js ได้สูงสุด 30 เท่า
  • รองรับตัวเลือก stream ของ TextDecoder
    • แม้ chunk จะไม่ใช่ UTF-8 code point ที่สมบูรณ์ ก็สามารถประมวลผลเป็นส่วนหนึ่งของ stream ที่ใหญ่กว่าได้
  • เพิ่มเมธอด bytes()
    • คืนค่า stream data เป็น Uint8Array จาก Response, Blob, Bun.file() เป็นต้น
    • ลดขั้นตอนเดิมที่ต้อง arrayBuffer() แล้วสร้าง Uint8Array
  • รองรับ streaming upload ด้วย fetch()
    • มีประโยชน์สำหรับอัปโหลดไฟล์ขนาดใหญ่หรือ stream data ที่ไม่รู้ content length ล่วงหน้า
  • implement console.group() และ console.groupEnd()
  • รองรับ URL.createObjectURL()
    • สร้าง URL จาก Blob แล้วใช้กับ fetch(), Worker, import() ได้
    • Worker script ก็ผ่าน Bun transpiler เช่นกัน จึงใช้ syntax ของ TypeScript ได้
  • AbortSignal.any() รวม AbortSignal หลายตัวเข้าด้วยกัน ทำให้เมื่อมีตัวใดตัวหนึ่ง abort แล้ว signal หลักก็ abort ด้วย

การเปลี่ยนแปลงพฤติกรรมและข้อควรระวังในการไมเกรต

  • ไดเรกทอรีทำงานของ bun run เปลี่ยนไป
    • ก่อนหน้านี้จะใช้ไดเรกทอรีทำงานปัจจุบันของ shell
    • ใน Bun 1.2 จะใช้ไดเรกทอรีแม่ของ package.json เป็นไดเรกทอรีทำงานของสคริปต์
    • เป็นการเปลี่ยนแปลงเพื่อให้สอดคล้องกับพฤติกรรมของ npm และ yarn
  • bun test จะรายงาน uncaught error หรือ rejection ระหว่างการทดสอบเป็นความล้มเหลว
    • ก่อนหน้านี้ข้อผิดพลาดลักษณะนี้อาจไม่ถูกจัดเป็นการทดสอบล้มเหลว
  • ตอนนี้ server.stop() คืนค่า Promise<void>
    • สามารถรอจนกว่า in-flight HTTP connection จะปิดได้
  • เมื่อ Bun.build() ล้มเหลว จะ reject แทนการใส่ข้อผิดพลาดไว้ใน logs ของผลลัพธ์ที่ resolve แล้ว
    • หากต้องการพฤติกรรมเดิม สามารถตั้งค่า throw: false ได้
  • bun -p กลายเป็น alias ของ bun --print เพื่อให้สอดคล้องกับ Node.js
    • ก่อนหน้านี้เป็น alias ของ bun --port
  • ค่าเริ่มต้นของ bun build --sourcemap เปลี่ยนจาก inline source map เป็น linked source map
    • หากต้องการพฤติกรรมเดิม ให้ใช้ --sourcemap=inline

การปรับปรุงประสิทธิภาพ

  • Bun 1.2 มี การปรับปรุงประสิทธิภาพ ในหลายเส้นทางการทำงาน
    • node:http2: เร็วขึ้น 2 เท่า
    • การอัปโหลด S3 ผ่าน node:http: เร็วขึ้น 5 เท่า
    • path.resolve(): เร็วขึ้น 30 เท่า
    • การทำ DNS resolution ของ fetch(): เร็วขึ้น 2 เท่า
    • bun --hot: ใช้หน่วยความจำลดลง 2 เท่า
    • fs.readdirSync() บน macOS: อ่านไดเรกทอรีขนาดเล็กเร็วขึ้น 5%
    • String.at(): เร็วขึ้น 44%
    • atob() สำหรับอินพุตสตริงขนาดใหญ่: เร็วขึ้นสูงสุด 8 เท่า
    • การคลายการบีบอัดข้อมูล gzip ของ fetch(): เร็วขึ้น 30%
    • Buffer.from(string, "base64") สำหรับอินพุตขนาดใหญ่: เร็วขึ้น 6–30 เท่า
    • JSON.parse() สำหรับอินพุตสตริงขนาดใหญ่: เร็วขึ้น 2–4 เท่า, อินพุต object เร็วขึ้น 6%
    • throughput ของแอปพลิเคชัน Bun.serve() บางส่วน: เพิ่มขึ้นสูงสุด 2 เท่า
    • Error.captureStackTrace(): เร็วขึ้น 9 เท่า
    • fs.readFile() สำหรับไฟล์ขนาดเล็ก: เร็วขึ้นสูงสุด 10%
    • console.log() ที่รับอาร์กิวเมนต์เป็นสตริง: เร็วขึ้น 50%
  • บน Windows เปิดใช้งาน JIT ของ JavaScriptCore แล้ว
    • ก่อนหน้านี้ JIT ใช้ได้เฉพาะบน macOS และ Linux
    • JavaScript บน Windows โดยรวมจะทำงานเร็วขึ้น
    • ตัวอย่างเช่น Object.entries() เร็วขึ้น 20% และ Array.map() เร็วขึ้น 50%

การติดตั้งและอัปเกรด

  • คำสั่งติดตั้งใหม่
    • curl -fsSL https://bun.sh/install | bash
    • powershell -c "irm bun.sh/install.ps1 | iex"
    • npm install -g bun
    • หลังจาก brew tap oven-sh/bun ให้ใช้ brew install bun
    • docker pull oven/bun
  • Bun ที่ติดตั้งไว้แล้วให้อัปเกรดด้วย bun upgrade

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

 
GN⁺ 2025-01-25
ความคิดเห็นจาก Hacker News
  • ไม่เข้าใจว่าทำไมถึงเอา ฐานข้อมูลของบุคคลที่สาม กับ ไลบรารี S3 ภายนอก ใส่ไว้ใน core/standard library
    ของแบบนี้น่าจะเหมาะเป็นไลบรารีให้เลือกใช้มากกว่า และ runtime แบบนี้ควรคัดเลือกสิ่งที่จะใส่ใน standard library อย่างระมัดระวังมาก
    เริ่มให้ความรู้สึกเหมือนโปรเจกต์ที่ใส่ทุกอย่างสารพัดลงไปเหมือนอ่างล้างจานในครัวแล้ว

    • ผมมองว่าจุดยืนแบบนี้เองเป็นหนึ่งในเหตุผลที่ Bun ได้รับความสนใจ
      แนวทางแบบ มีแบตเตอรี่ให้ครบ เป็นแนวทางที่ได้รับความนิยมและถูกเลือกใช้ในหลายที่
      การตั้งค่า TypeScript ก็ยาก Webpack, S3, Postgres, Jest ก็เช่นกัน ดังนั้นการเข้าถึงไฟล์และสตรีมที่เรียบง่ายขึ้นก็น่าสนใจพอสมควร
      คงต้องรอดูว่าผู้ให้บริการ deploy แบบกระจายจะออกมาอย่างไร
    • เท่าที่รู้ Bun ได้เงินลงทุนจาก VC ดังนั้นสักวันก็ต้องทำเงิน และถ้าให้เดา ก็อาจกำลังทำให้เป็น ตัวรันแบบ all-in-one เพื่อสร้าง vendor lock-in ในรูปแบบใดรูปแบบหนึ่ง
      แน่นอนว่าอาจเดาผิดก็ได้ แต่การเอา dependency แบบนี้ใส่ใน core/standard library จริง ๆ แล้วไม่ค่อยสมเหตุสมผล
    • หลายคนเคยพูดเรื่องเดียวกันกับ Jared ผู้เขียน Bun แล้ว แต่แนวคิดของ Jared คือ Bun ควรมีทุกอย่างที่โปรเจกต์พื้นฐานต้องใช้มาให้พร้อม
      ดูเหมือนเขามองว่าถ้าใส่ไว้ใน core จะ optimize ได้ดีกว่าไลบรารีของบุคคลที่สาม
      ส่วนตัวคิดว่าเป็นแนวทางที่ผิด และรู้สึกว่า Jared มีความทะเยอทะยานมากเกินไป แต่สุดท้ายมันก็เป็นโปรเจกต์ที่เขาทุ่มเทด้วยใจจริง ๆ
    • เห็นด้วยเต็มที่ว่าไลบรารีให้เลือกใช้ดีกว่า
      ตามคำอธิบายของฝั่ง Bun คือ “Bun มุ่งเป็น JavaScript runtime ที่ให้ความสำคัญกับคลาวด์ก่อน กล่าวคือรองรับเครื่องมือและบริการทั้งหมดที่จำเป็นสำหรับการรันแอปพลิเคชัน production บนคลาวด์” แต่คำพูดนี้ไม่ได้ทำให้รู้สึกน่าเชื่อถือเท่าไร
      การตัดสินใจด้านการออกแบบเฉพาะจุดนี้ดู แย่กว่า Node เสียอีก
    • นี่มีไว้สำหรับ บริการแบบ managed ของ Bun
      ปัญหาของซอฟต์แวร์ที่มี VC หนุนหลังมักเป็นแบบนี้เสมอ คือฟีเจอร์ผสานรวมเหล่านี้พยายามจะนำเสนออะไรบางอย่างที่เป็นเอกลักษณ์ หรือพูดอีกอย่างคือพยายามสร้างการผูกติด
  • ประสบการณ์ใช้ Bun ที่ผ่านมาดีมาก
    เวลาตั้งค่า TypeScript/Jest/React/Webpack ในโปรเจกต์ใหม่ ผมมักเลี่ยงเพราะมี breaking changes จากหลายทางตลอด แต่ใน Bun มันจัดการได้เอง และสำหรับ use case ของผมก็ใช้งานได้เลยโดยไม่เจ็บปวด
    การผสานรวมไลบรารีของบุคคลที่สามอย่าง S3, SQL นั้นพูดยาก แต่ดูเหมือนอย่างน้อยก็โฟกัสสิ่งที่ใช้กันแพร่หลายที่สุดและมีคนขอมากที่สุด
    ดีที่มันนำความเป็นปกติที่ ระบบนิเวศเครื่องมือของ Node.js ต้องการกลับมาให้

    • อยากรู้ว่า Bun สร้างความแตกต่างอะไรให้กับ frontend tech stack ที่พูดถึงข้างบน
    • โปรเจกต์ React/TypeScript ก็ตั้งค่าได้ดีด้วย Vite หรือ Next.js อยู่แล้ว
      ดูเหมือนจะประเมินต่ำไปว่าเครื่องมืออื่น ๆ ก็พัฒนาขึ้นมากในช่วงที่ผ่านมาเหมือนกัน
    • Bun ยอดเยี่ยมมาก
      สำหรับผมมันเหมือน สูตรโกงด้าน productivity
      แม้จะมี productivity loss เล็กน้อยเพราะ ChatGPT ไม่ค่อยรู้จัก Bun ดี แต่ก็ยังชอบ Bun อยู่ดี
  • มีหลายอย่างที่ดี แต่กังวลว่าพฤติกรรมเริ่มต้นบางส่วนจะกลายเป็น พฤติกรรมที่ซ่อนอยู่เหมือนเวทมนตร์ มากเกินไปหรือเปล่า
    ถ้าใช้ new Response(s3.file(...)) แทนที่ Bun จะดาวน์โหลดไฟล์ S3 มายังเซิร์ฟเวอร์แล้วส่งให้ผู้ใช้ Bun จะ redirect ผู้ใช้ไปยัง presigned URL ของไฟล์ S3
    ในฐานะค่าเริ่มต้นถือว่าเป็นทางเลือกที่ค่อนข้างน่าประหลาดใจ และก็ไม่ชัดเจนเลยว่าจะปิดอย่างไรเมื่อไม่อยาก expose bucket S3 โดยตรง

    • ผมเคารพพื้นที่ที่ Bun พยายามบุกเบิก แต่ถ้าตามผู้สร้างบน Twitter จะเห็นว่าการตัดสินใจเอนเอียงไปทางผลลัพธ์ระยะสั้นและความสะดวกค่อนข้างมาก และมักมอง ผลกระทบเชิงลึกของพฤติกรรมเวทมนตร์เหล่านั้น แบบเบาไป
      ตอนแรกผมคาดหวังกับโปรเจกต์นี้ แต่เมื่อเห็นการตัดสินใจด้านการออกแบบที่กระจัดกระจายและส่วนตัวมักคิดว่าไม่ดีซึ่งถูกเปิดเผยบนโซเชียล ก็ทำให้ไม่มั่นใจในทิศทางระยะยาว
      ถ้ายังอยู่ที่ v0.x ก็คงโอเค แต่เมื่อออก 1.0 แล้ว มาตรฐานในการเพิ่ม API surface ควรสูงกว่านี้มาก
    • ก็ส่ง stream เข้าไปใน response ได้
      Response(file.stream())
    • เข้าใจว่าทำไมถึงทำแบบนั้น แต่ไม่ชอบดีไซน์นี้
      ส่วนตัวรู้สึกเหมือนเป็น พฤติกรรมที่มี side effect แรง และเวลาอ่านดูเหมือนจะคืนเนื้อหาไฟล์ ไม่ใช่ URL
      ถึงอย่างนั้นก็สงสัยเหมือนกันว่าการ expose bucket มันน่ารำคาญตรงไหน
      เพราะเป็น presigned URL ไม่ได้ให้สิทธิ์เข้าถึงแบบกว้าง ๆ
      API ที่ชัดเจนอย่าง Response((file(...).getPresignedURL())) น่าจะดีกว่า หรือไม่ก็มีตัวเลือกให้เปิดพฤติกรรมนี้ผ่าน environment variable หรือการตั้งค่า Bun น่าจะเหมาะกว่า
  • รวมแบตเตอรี่ในตัว สร้างความแตกต่างได้มาก
    นี่เป็นเหตุผลที่ชอบที่เว็บ API อย่าง Fetch API, Service Workers, Web Components, ES6+, WebRTC ตอนนี้กลายเป็นของเนทีฟทั้งในรันไทม์ V8 และ WebKit
    แต่ก็ต้องมีขอบเขต
    S3 อาจจะไปไกลเกินไป แต่ไดรเวอร์ SQL นั้นสมเหตุสมผล
    ถึงอย่างนั้น ปัญหาคือจะใส่เข้าไปถึงไหน
    ฐานข้อมูลมีเยอะมาก แล้วต้องใส่ไดรเวอร์ของครึ่งหนึ่งในนั้นด้วยไหม?
    แค่ถึงระดับนั้นก็มีโค้ดเพิ่มขึ้นมากพอที่จะทำให้ไฟล์ executable ช้าลงได้
    อีกอย่าง การใส่ API ที่อ่อนไหวแบบนี้ไว้ใน Bun ก็อาจทำให้พลาดเรื่องความปลอดภัยได้
    ลองจินตนาการว่าสคริปต์บางตัวหรือปัญหาเรื่อง path ทำให้ eval ถูกรัน แล้ว Bun อัปโหลดซอร์สไฟล์ทั้งหมดไปยัง S3 ส่วนตัว เท่านั้นก็จบแล้ว

    • สงสัยจริง ๆ ว่า “โค้ดเพิ่มขึ้นมากแล้วไฟล์ executable จะช้าลง” เป็นอย่างนั้นจริงไหม
      เคยเห็นว่าขึ้นอยู่กับวิธีที่โค้ดถูกโหลดตอนรันไทม์ มันอาจแทบมองข้ามได้
      ถ้าการโหลดโค้ดถูก trigger เฉพาะเมื่อเห็นคำสั่ง import งั้นแทบไม่มี overhead ด้านความเร็วเลยไม่ใช่หรือ?
      ต่อให้ลิงก์แบบ static ก็ยังไม่ค่อยเข้าใจว่าทำไมแค่มีโค้ดอยู่จึงทำให้ไฟล์ executable ช้าลงในระดับที่ควรคำนึงถึง
      อาจมีแค่ขนาดไฟล์ executable ที่ต้องโหลดเข้า memory ใหญ่ขึ้นตามตัวอักษร แต่ไม่น่าจะเป็นความช้าลงที่รู้สึกได้
    • เคยมีการถกกันใน HN ว่าทำไมเบราว์เซอร์ไม่รองรับ SQLite แบบ first-class ซึ่งประเด็นนั้นอาจนำมาใช้กับ Bun ได้ด้วย
      แก่นคือใครเป็นผู้รับผิดชอบดูแลไลบรารี และเมื่อ SQLite เปลี่ยน จะเปลี่ยนไลบรารีนั้นอย่างไร
      ถ้า SQLite มีบั๊ก ใน Bun จะแก้อย่างไร?
      ต้องแก้ในเวอร์ชันไหนบ้าง?
      แพตช์ของรันไทม์อาจเปลี่ยนพฤติกรรมของโค้ดที่รันอยู่บนมัน แล้วจะจัดการอย่างไรถ้าผู้ใช้ทำ workaround ไว้ให้เข้ากับพฤติกรรมเดิมแล้ว?
      ในระดับหนึ่งเป็นปัญหาที่แก้ได้ แต่ก็มีข้อเสียตามมา
      เมื่อถึงจุดหนึ่ง มันจะไม่ใช่รันไทม์ แต่กลายเป็น แพลตฟอร์ม และมาพร้อมความรับผิดชอบกับปัญหาแบบอื่น
    • เหตุผลของฝ่ายที่อยากใส่ S3 น่าจะอยู่ที่มีบริการ object storage จำนวนมากที่ implement API ที่เข้ากันได้กับ S3
      ไม่ใช่มาตรฐานเว็บจริง ๆ แต่ก็เป็นสิ่งที่คนจำนวนมากปรับให้เข้ากันและใช้เหมือนเป็นมาตรฐานโดยพฤตินัย
    • ถึงจะบอกว่า “โค้ดเพิ่มขึ้นมากแล้วไฟล์ executable จะช้าลง” แต่ในบทความมี benchmark ตรง ๆ และบอกว่า Bun เร็วกว่า โซลูชัน Node.js ที่เร็วที่สุด สองเท่า
  • ช่วงนี้ลูกค้าใช้ Bun ใน production
    ได้ยินมาว่า developer experience ของ Bun ดีแบบเหลือเชื่อเพราะความเร็วและความเรียบง่าย
    developer experience มีบทบาทใหญ่ในระยะยาว
    ถ้า codebase หรือ process เละเทะ ก็จะเสียคนเก่ง ๆ ไป เว้นแต่จะให้ค่าตอบแทนระดับ FAANG

  • ยังไม่เคยลองใช้ Bun แต่รายการฟีเจอร์ยาวมากจนสงสัยว่าทั้งหมดจะแข็งแรงและไม่มีบั๊กจริงหรือไม่
    หวังว่าจะคิดผิด และตั้งใจจะลองรันในโปรเจกต์ภายหลัง
    จากมุมมองการจัดการโปรเจกต์ ค่อนข้างสับสนว่าทำไมถึงเอาเวลาไปทำการรองรับ S3 ทั้งที่ยังไม่ได้ เข้ากันได้กับ Node.js 100%
    Next.js เป็น ecosystem ที่ใหญ่มาก ถ้าดึงลูกค้า Next.js มาได้ ก็น่าจะเติบโตได้มากกว่าการรองรับ S3 มาก

    • ความเข้ากันได้ 100% เป็นชัยชนะที่ดีในเชิงการตลาด แต่ความเข้ากันได้ในส่วน long tail อาจไม่ได้สร้างความแตกต่างมากนักต่อผู้ใช้ทั่วไป
      ในชีวิตประจำวัน คุณใช้ พื้นผิว API ของ Node.js ทั้งหมดจริง ๆ แค่ไหน?
      และพึ่งพา edge case แปลก ๆ ในนั้นจริง ๆ แค่ไหน?
    • คำว่า “จากมุมมองการจัดการโปรเจกต์” สมมติว่ารู้ว่าโปรเจกต์คืออะไร
      คนที่ทำงานอยู่ก็ไม่ใช่หุ่นยนต์
      บางงานต้องใช้เวลาในการทำความเข้าใจ และระหว่างนั้นก็ทำงานอื่นได้
      ไม่ใช่ว่าคนเดียวทำทุกอย่าง
      บอกว่า “ถ้าดึงลูกค้า Next.js มาได้จะเติบโตมากขึ้น” แต่เติบโตไปสู่อะไร?
      นั่นไม่ได้ทำเงิน
      นี่เป็นโปรเจกต์ที่ได้รับการสนับสนุนจาก VC และเป้าหมายไม่ใช่การแจก Bun ฟรีเพื่อให้ได้ผู้ใช้ทั้งโลก
    • ที่สงสัยว่ารายการฟีเจอร์ยาว ๆ ทั้งหมดจะแข็งแรงและไม่มีบั๊กไหม โดยเฉพาะติดตรงที่ เขียนด้วย Zig
      Zig มีความปลอดภัยด้านหน่วยความจำต่ำมาก
      ถ้าอ้างอิงตัวแปรที่ไม่ยังมีชีวิตอยู่แล้ว มันจะเข้าถึงหน่วยความจำอื่นที่ไม่เกี่ยวข้องแบบสุ่มแทนที่จะเกิด segmentation fault
      ว่ากันว่าเป็นแบบนั้นแม้ใน debug และ safe mode[0]
      การวางระบบ lifetime ของหน่วยความจำไว้ด้านบน ที่ทำเครื่องหมายชื่อตัวแปรว่า dead แล้วห้ามเข้าถึงถ้ามันตายแล้ว มันยากขนาดนั้นเลยหรือ?
      สุดท้ายก็กลายเป็น “อย่าใช้ undefined behavior”[1]
      เพราะงั้นจึงไม่อยากวางอะไรที่ทำด้วย Zig ไว้ในที่อย่างเว็บเซิร์ฟเวอร์ที่เปิดสู่ internet
      [0] : https://news.ycombinator.com/item?id=41720995
      [1] : https://github.com/ziglang/zig/issues/16467#issuecomment-164...
    • ไม่ได้แข็งแรงมาก และไม่ได้ไม่มีบั๊ก
      เคยลองใช้ปีที่แล้ว แล้วมัน crash อยู่เรื่อย ๆ
    • รายการที่บอกว่าแก้บั๊กที่ bun add ไม่รักษาช่องว่างและ indentation ใน package.json แล้ว ตอนนี้รักษาได้แม้ indentation จะแปลกแค่ไหน นี่ค่อนข้างขำ
      ไม่รู้ว่าใครขอสิ่งนี้ และทำไมถึงคิดว่าคุ้มค่าที่จะเขียนโค้ดเพื่อมัน
  • การนำเข้า HTML นั้นยอดเยี่ยมและเท่มาก
    ใน Bun 1.2 รองรับการนำเข้า HTML แล้ว และบอกว่าสามารถแทนที่ toolchain ฝั่ง frontend ทั้งหมดได้ด้วยคำสั่ง import เพียงคำสั่งเดียว
    เริ่มได้โดยส่งการนำเข้า HTML ให้กับตัวเลือก static ของ Bun.serve

    import homepage from "./index.html";
    
    Bun.serve({  
      static: {  
        "/": homepage,  
      },
    
      async fetch(req) {  
        // ... api requests  
      },  
    });  
    
    • สงสัยว่าสิ่งนี้ช่วยแทนที่ Vite ได้อย่างไร เช่น
      สามารถโหลดปลั๊กอินเฉพาะเฟรมเวิร์กอย่าง hot module replacement, CSS preprocessing, Vue SFC compiler ได้ไหม?
      การเสิร์ฟไฟล์ static ไม่ใช่เรื่องใหม่อะไร เลยรู้สึกเหมือนว่าผมอาจพลาดอะไรไป
  • ผมเคยคิดว่าไม่มีโปรเจกต์ไหนที่ถูกลิขิตให้ล้มเหลวเท่ากับทางเลือกคู่แข่งของ Node.js แล้ว แต่พอได้ลองใช้ดูก็ถือว่าคิดถูกที่ลอง
    ผมต้องทำสคริปต์แบบสแตนด์อโลนจำนวนมากสำหรับจัดการอัปเดตไฟล์ข้อความและฐานข้อมูล SQLite และสามารถใช้ TypeScript, bun:sqlite [1], bun $ Shell [2] ได้ทันทีโดยไม่ต้องมีไฟล์คอนฟิกหรือจัดการ dependency ของ npm แบบโลคัล
    หลังจากนั้นก็ลองใช้กับโปรเจกต์ JS/TypeScript ใหม่ ๆ ด้วย ซึ่งได้ใช้ทั้ง bundler ในตัว [3] และการรองรับการทดสอบ [4] แถมติดตั้ง dependency เสร็จแทบทันที
    การที่ทุกอย่างทำงานได้ทันทีอย่างรวดเร็วนั้นเป็นการยกระดับคุณภาพชีวิตจริง ๆ และตอนนี้ Bun กลายเป็น ตัวเลือกแรก สำหรับโปรเจกต์ JS ใหม่ของผมแล้ว
    [1] https://bun.sh/docs/runtime/shell
    [2] https://bun.sh/docs/api/sqlite
    [3] https://bun.sh/docs/bundler
    [4] https://bun.sh/docs/cli/test

    • ผมก็เหมือนกัน
      ผมเคยอยู่ฝั่งที่คิดว่า “ของพวกนี้ปีหน้าก็คงมีใน npm หมดแล้ว มันจะมีความหมายอะไร”
      สุดท้ายได้ลองใช้ Bun แล้วก็ประหลาดใจจริง ๆ
      เมื่อ รายละเอียดเล็ก ๆ ของประสบการณ์นักพัฒนา สะสมกัน มันสร้างความแตกต่างได้มาก
      ในโปรเจกต์ของผม Bun ให้ความรู้สึกเหมือนเป็นเจเนอเรชันถัดไปจริง ๆ
  • เมื่อไม่นานมานี้ผมได้ลองใช้ Bun เป็นครั้งแรก และประสบการณ์ดีมาก
    โปรเจกต์ทั้งหมดของผมตั้งค่า Webpack หรือ Vite ไว้เพื่อใช้ TypeScript และเมื่อตั้งค่าแล้วก็มักทำงานได้เกือบสมบูรณ์แบบ แต่การตั้งค่านั้นยุ่งยาก และไม่คุ้มสำหรับสคริปต์เล็ก ๆ
    แต่ Bun กลับใช้งานได้ทันที
    ตอนพยายามรัน TS “โดยตรง” จาก CLI ผมนั่งงมกับเครื่องมือที่ชื่อ node-ts หรืออะไรทำนองนั้นอยู่ 10–30 นาที เจอข้อความชวนสยองอย่าง “ไม่ใช่โมดูล”, “ใช้ import/require ไม่ได้”, “ESM/CJS” และลองวิธีแก้ที่พบบ่อยทั้งหมดแล้ว ทั้งเปลี่ยนชนิดโมดูลใน package.json, เปลี่ยน tsconfig, เปลี่ยนวิธีใช้ import/require
    พอกำลังจะรันสคริปต์ประมาณ 200 บรรทัด แล้วเปลี่ยนมาใช้ Bun เป็นทางเลือกสุดท้าย มันก็ทำงานได้อย่างยอดเยี่ยม

    • Node.js รุ่นล่าสุดตอนนี้ก็รองรับ “รัน TS ได้เลย” สำหรับกรณีแบบนี้แล้ว
      node --experimental-strip-types index.ts
      ถ้าไม่ใช่ Node รุ่นล่าสุด แพ็กเกจ tsx ก็ทำงานได้ดีสำหรับผม
      ดีกว่า ts-node
      แต่ทั้งสองทางเลือกก็แค่ทิ้งข้อมูลชนิดไปเฉย ๆ และ Bun ก็เหมือนกัน
  • ชอบทิศทางนี้
    โดยเฉพาะการใส่การรองรับ S3 และ Postgres แบบเนทีฟ เข้ามา เป็นสิ่งที่สมเหตุสมผลมาก เพราะมันสามารถเป็นทางเลือกให้กับสถานะปัจจุบันที่ต้อง “ประกอบ framework เอง” ได้
    ในเว็บเฟรมเวิร์กแบบครบเครื่องอย่าง Rails และ Laravel ทั้งหมด สิ่งนี้เป็นมาตรฐานอยู่แล้ว และ ecosystem ของ JS ก็จะได้ประโยชน์มากจากตรงนี้
    ผมมองว่าขั้นต่อไปคือ migration กับการจัดการ schema และประสบการณ์ทดสอบพื้นฐานที่ดีกว่า ซึ่งตั้งค่า factory ได้ดี