มารู้จัก Bun runtime และ ElysiaJS กัน

/ 4 min read

Share on social media

bun-elysia สามารถดู video ของหัวข้อนี้ก่อนได้ ดู video

รู้จักกับ Runtime ก่อน

เราต้องทำความเข้าใจก่อนว่า runtime environment คืออะไร ?

  • Runtime environment (จากนี้ขอเรียกสั้นๆว่า runtime) คือ software ที่ใช้สำหรับการ run program ซึ่งจะรองรับตามภาษาที่มีการกำหนดตาม spec ของ runtime นั้นเอาไว้ โดยไม่ได้อ้างอิงตามระบบ OS หรือ hardware โดยตัว runtime จะเป็นคนจัดการไว้ให้แทน

โดยไอเดียของ runtime คือ

  • runtime จะทำการ Execution code เพื่อทำตาม function ที่ program นั้นเขียนมา
  • ตัว runtime มักจะมาพร้อมกับ standard library อย่าง การจัดการ file, network, GUI ซึ่งเป็นสิ่งที่ช่วยอำนวยความสะดวกในการ run program มากขึ้น
  • มีตัวคอยจัดการ Resource memory และ system รวมถึง feature จัดการ memory อย่าง garbage collection เพิ่มให้กับตัว programming เพื่อให้สามารถจัดการกับ memory ได้ดียิ่งขึ้น
  • runtime บางตัว มีความสามารถในการ Interpreting Code or Just-in-Time compile code เพื่ออำนวยความสะดวกในการ run software

ตัวอย่าง runtime ที่เป็นที่นิยมในปัจจุบัน

  • JVM (Java Virtual Machine)
  • .Net (Common Language Runtime)
  • Node.js (Javascript Runtime ฝั่ง Server side)

ดังนั้น เวลา run software runtime จึงเป็นองค์ประกอบสำคัญที่ทำให้ software ไวขึ้นด้วยเช่นกัน (แม้ว่าจะเป็นภาษาเดิมก็ตาม)

ดังนั้น การเปลี่ยน runtime = สามารถ improve performance ของตัว software ได้ เช่นกัน

ตัวอย่าง runtime ของ CLR CLR-runtime

Ref: https://www.researchgate.net/figure/Common-Language-Runtime-diagram_fig30_281837118

Bun คืออะไร ?

Ref: https://bun.sh/docs#what-is-a-runtime

Javascript (หรือให้ทางการขึ้นคือ ECMAScript) เป็น spec สำหรับภาษา programming โดยที่ developer สามารถเขียน Javascript engine นี้ได้ ขอแค่ให้ run javascript ได้ตาม spec = เป็น engine ที่สามารถ run program javascript ได้

ปัจจุบัน engine ที่ popular ในปัจจุบันคือ V8 (โดย Google) และ JavaScriptCore (โดย Apple)

ทีนี้ เราต้องมาเล่าถึง Node.js ก่อน

  • Node.js คือ Javascript runtime สำหรับการ run javascript แบบ non-browser environments ใช้สำหรับการ run javascript ฝั่ง Server
  • โดย Javascript สามารถ run บน runtime Node.js ได้และใช้ความสามารถผ่าน runtime node.js อย่าง Buffer, process, เขียน file, network (node:net, node:http) รวมถึง build-in module ที่สามารถทำงานร่วมกับ OS ของเครื่องนั้นได้
  • เท่ากับ Node.js ได้ implements javascript runtime ที่พร้อมใช้งานสำหรับ Javascript ไว้แล้ว

มันเลยเป็นโจทย์ของ Bun ที่ได้ทำการ design runtime ใหม่ ที่ไวขึ้น และ มีความสามารถมากขึ้นเพื่อนำมาแทนที Node.js ได้

Bun คือ runtime environment ตัวใหม่ของ Javascript ที่มาพร้อมกับ package manager ถือกำเนิดในช่วงปี 2022 ที่ผ่านมา

จุดแตกต่างใหญ่ๆ ที่แตกต่างระหว่าง Bun และ Node.js คือ

  1. ภาษาที่ใช้พัฒนา
  • Node.js พัฒนาจาก C++
  • Deno พัฒนาจาก Rust
  • Bun พัฒนาจาก Zig

โดยทั้ง 3 runtime พัฒนามาจาก low-level ทั้งหมด

  1. ความเข้ากันได้ของ web browser engine
  • Node.js และ Deno ใช้ V8 Engine
  • Bun ใช้ Webkit มาต่อยอดทำ runtime ซึ่งมีประสิทธิภาพมากกว่า เลยทำให้มีผล benchmark ที่โดดเด่นกว่า Node.js และ Deno

โดย Bun มีคุณสมบัติที่โดดเด่นคือ

  • Speed: process ไวขึ้นกว่า node.js 4x
  • TypeScript & JSX support: รองรับการใช้งานกับ .jsx, .ts, .tsx ได้
  • ESM & CommonJS compatibility: Support ทั้ง ES modules และ CommonJS
  • Web-standard APIs: implement standard Web API อย่าง fetch, WebSocket, ReadableStream
  • Node.js compatibility: support กับหลายๆ module ของ node.js สามารถตรวจสอบได้ผ่าน https://bun.sh/docs/runtime/nodejs-apis
  • More than runtime: รวมถึงมี feature อื่นๆ ที่นอกเหนือจาก runtime อย่าง package manager, transpiler, bundler, script runner, test runner และอื่นๆอีกมากมาย
node-bun-runtime

Ref: https://willkencel.medium.com/bun-what-it-is-and-what-are-its-implications-for-software-engineers-c323d966cf0f

และในวันที่ 8 กันยายน 2023 ที่ผ่านมา Bun ก็ได้ public version 1.0 เป็นที่เรียบร้อย

bun

เรามาลองดูตัวอย่างของ code bun กัน

Terminal window
curl -fsSL https://bun.sh/install | bash

** สำหรับใครที่ใช้ Windows อาจจะมี limitation support หลายอย่าง แต่ bun runtime สามารถ run native windows ได้แล้ว

  • ขั้นที่สอง สร้าง http server ผ่าน bun
index.tsx
const server = Bun.serve({
port: 3000,
fetch(request) {
return new Response("Welcome to Bun!");
},
});
console.log(`Listening on localhost:${server.port}`);
  • ขั้นตอนสุดท้าย run ด้วยคำสั่ง
Terminal window
bun index.tsx

ก็จะได้ผลลัพธ์เป็น HTTP Server ออกมา

อย่างที่เห็น

  • แม้ว่าจะเปลี่ยน runtime แต่พื้นฐานยังคงเป็นภาษา Javascript เหมือนเดิม
  • ดังนั้น หากใครใช้ Javascript อยู่แล้ว การพัฒนาจะไม่ต่างจากเดิมมาก (แค่ต้องทำความเข้าใจ library พื้นฐานของตัว runtime เพิ่ม กับ วิธีการ compile ของตัว runtime เพิ่มแค่นั้น)

แนะนำ ElysiaJS และ Beth stack

Ref: https://elysiajs.com/introduction.html

ElysiaJS is a fast, and friendly Bun web framework.

โดย ElysiaJS สร้างอยู่บน 3 พื้นฐานใหญ่ๆ

  • Performance: ได้รับพลังจาก bun มา
  • Simplicity: code ง่าย
  • Flexibility: customize ได้ไม่ยาก
new Elysia().get("/id/:id", ({ params: { id } }) => id).listen(8080);
  • ElysiaJS ใช้สำหรับทำ Backend Server (ไอเดียเหมือนการ development Rest API ด้วย Express เลย)
  • ซึ่ง ตัว library ก็ได้คิดมาแล้วว่าต้องมีการใช้งานร่วมกับฝั่ง Frontend = library ได้เตรียม Eden ไว้สำหรับต่อฝั่งหน้าบ้านเรียบร้อย

ลองเล่น Elysia

Ref: https://elysiajs.com/quick-start.html

โจทย์ที่เราจะทำกัน

  • เราจะทำเว็บสำหรับจัดการข้อมูลหนังสือ Book Management ง่ายๆ
  • โดยเราจะใส่ Login เข้าไปใน web ด้วย (คนแก้ไขได้ต้องเป็นคนที่ login แล้วเท่านั้น)
  • พัฒนาโดย Bun ใช้ Elysia เป็น web framework และใช้ sqlite เป็น Database

เคสที่จะลอง

  1. CRUD กับ sqlite (ใช้ package bun) https://bun.sh/docs/api/sqlite
  • ทำ validation โดยใช้ schema
  • CRUD สำหรับการจัดการหนังสือ (/books) ใช้ parameter
  • ใช้ program DB Browser จัดการ SQLite (** สร้าง Database จาก DB Browser มาก่อน)
  1. login with jwt ด้วย cookie
  • register ด้วยการเข้ารหัส https://bun.sh/docs/api/hashing#bun-password
  • เพิ่ม login แล้วเก็บเข้า cookie ด้วย jwt
  • เพิ่ม derive สำหรับแกะข้อมูลจาก cookie ด้วย jwt token (verify jwt แล้วส่งต่อไปยัง API ปลายทาง)
  • เพิ่ม guard api สำหรับ validate ข้อมูล (recheck ว่า login มาจริงแล้วหรือไม่)
  • แนะนำเรื่อง onRequest เพิ่ม (global hook)
  1. เพิ่ม swagger สำหรับเอกสาร
  • อ่านตาม schema
  1. Eden (ตัวต่อฝั่ง Frontend) = ต่อ Client ผ่าน Eden
  • ลองใช้งานผ่าน React เพื่อดึงข้อมูลออกมา

Deploy งาน bun ยังไง

Ref:

ปัจจุบัน (จากที่ผมหาข้อมูลมา)

  • ยังไม่มีตัวไหน support bun แบบ native
  • ง่ายที่สุด คือใช้ docker ทำการสร้าง image bun (oven/bun) https://hub.docker.com/r/oven/bun/tags
  • ตัวอย่างนี้เดี๋ยวเราจะลอง deploy ขึ้น Cloud run กัน

โดย

  1. สร้าง Dockerfile ขึ้นมา
Dockerfile
FROM oven/bun
WORKDIR /app
COPY package.json .
COPY bun.lockb .
RUN bun install
COPY ./src ./src
COPY ./.env ./.env
EXPOSE 8000
CMD ["bun", "src/index.ts"]
  1. build dockerfile แล้วนำ docker image ขึ้น Artifact Registry
Terminal window
# Authentication Gcloud ก่อน
gcloud auth login
gcloud auth configure-docker asia-southeast1-docker.pkg.dev
# Build docker
docker build -t asia-southeast1-docker.pkg.dev/<project>/bun-test/bun-elysia-test --platform linux/x86_64 .
# Push ขึ้น Artifact Registry
docker push asia-southeast1-docker.pkg.dev/<project>/bun-test/bun-elysia-test
  1. ที่ Cloud run เรียกใช้งาน Artifact Registry
cloud-run-01 cloud-run-02

เมื่อ run เรียบร้อย ให้ลองเรียกผ่าน URL ดู

cloud-run-03 cloud-run-04

Reference

Related Post

Share on social media