Di antara alat pengembang terbaru yang paling menarik adalah Bun, sebuah toolkit JavaScript yang sangat cepat dan lengkap, dirancang untuk meningkatkan produktivitas pengembang dan kinerja aplikasi. Bun bukan sekadar runtime lain; ini adalah ekosistem yang kohesif yang mencakup runtime, bundler, test runner, package manager, dan lainnya, semuanya dalam satu executable native tunggal. Panduan ini akan memandu Anda melalui hal-hal penting tentang Bun, dengan fokus pada konsep inti dan API yang kuat.
Ingin platform All-in-One yang terintegrasi untuk Tim Pengembang Anda bekerja sama dengan produktivitas maksimum?
Apidog memenuhi semua permintaan Anda, dan menggantikan Postman dengan harga yang jauh lebih terjangkau!
Apa itu Bun?

Intinya, Bun dibangun di sekitar mesin runtime JavaScript berperforma tinggi. Berbeda dengan Node.js, yang menggunakan mesin V8 Google, Bun menggunakan JavaScriptCore (JSC) Apple, mesin yang mendukung Safari. Pilihan ini, dikombinasikan dengan implementasi Bun dalam bahasa pemrograman Zig tingkat rendah, berkontribusi signifikan terhadap kecepatannya yang luar biasa. Waktu startup untuk aplikasi Bun seringkali diukur jauh lebih cepat daripada aplikasi Node.js yang setara, terkadang dengan faktor empat atau lebih. Keunggulan kecepatan ini meluas melampaui startup; implementasi internal Bun dari berbagai API dioptimalkan untuk throughput maksimum dan penggunaan memori minimal.
Tetapi ambisi Bun melampaui sekadar menjadi runtime yang lebih cepat. Ini bertujuan untuk menjadi toolkit yang komprehensif, menangani kebutuhan pengembang umum secara langsung:
- Alat Terintegrasi: Perintah
bun
itu sendiri bertindak sebagai titik masuk untuk berbagai fungsi.bun run
mengeksekusi skrip yang ditentukan dalampackage.json
,bun install
mengelola dependensi (seringkali jauh lebih cepat daripada npm atau yarn),bun test
menjalankan tes menggunakan API yang kompatibel dengan Jest,bun build
menggabungkan kode untuk produksi, danbunx
mengeksekusi paket tanpa menginstalnya secara eksplisit. Integrasi ini menyederhanakan alur kerja dengan mengurangi jumlah alat pengembangan yang berbeda yang dibutuhkan. - Dukungan Native TypeScript dan JSX: Salah satu fitur unggulan Bun adalah dukungan siap pakai untuk file TypeScript (
.ts
,.tsx
) dan JSX (.jsx
). Bun menyertakan transpiler bawaan yang sangat dioptimalkan yang menangani jenis file ini secara mulus selama eksekusi atau bundling. Ini menghilangkan kebutuhan untuk langkah kompilasi terpisah yang melibatkantsc
atau Babel untuk banyak skenario pengembangan umum, merampingkan proses pengaturan. - Kompatibilitas Sistem Modul: Bun merangkul JavaScript modern dengan dukungan kelas satu untuk ES Modules (ESM). Namun, ia mengakui ekosistem luas yang ada yang dibangun di atas CommonJS (CJS). Bun menyediakan kompatibilitas yang kuat untuk kedua sistem modul, memungkinkan pengembang untuk menggunakan
import
danrequire
sebagian besar secara bergantian dan memanfaatkan jutaan paket CJS yang ada yang tersedia di npm. - Kepatuhan API Standar Web: Prinsip desain utama adalah implementasi API Web standar. Fungsi dan objek seperti
fetch
,Request
,Response
,Headers
,WebSocket
, dan Streams API (ReadableStream
,WritableStream
) dibangun ke dalam cakupan global Bun. Ini mendorong portabilitas kode antara lingkungan Bun sisi server, frontend browser, dan platform komputasi edge, memungkinkan pengembang untuk menggunakan kembali API yang familiar di berbagai konteks. - Kompatibilitas Node.js: Sementara menempuh jalannya sendiri dengan API yang dioptimalkan dan standar Web, Bun bertujuan untuk tingkat kompatibilitas yang tinggi dengan permukaan API Node.js. Banyak modul Node.js bawaan (
node:fs
,node:path
,node:os
,node:events
, dll.) dan objek global (process
,Buffer
,__filename
,__dirname
) diimplementasikan sebagian atau seluruhnya. Tujuannya adalah untuk memungkinkan banyak proyek Node.js dan paket npm yang ada berjalan di Bun dengan sedikit atau tanpa modifikasi, memposisikan Bun sebagai "pengganti langsung" dalam banyak kasus.
Dengan menggabungkan elemen-elemen ini, Bun menghadirkan alternatif yang menarik bagi pengembang JavaScript dan TypeScript yang mencari kinerja, kesederhanaan, dan pengalaman pengembangan modern.

Cara Menginstal Bun
Memulai dengan Bun dirancang agar cepat dan mudah di berbagai platform. Metode paling umum untuk macOS, Linux, dan Windows Subsystem for Linux (WSL) menggunakan perintah curl
sederhana yang dieksekusi di terminal Anda:
curl -fsSL https://bun.sh/install | bash
Perintah ini mengunduh skrip instalasi dan mengirimkannya langsung ke bash
. Skrip menangani deteksi sistem operasi dan arsitektur Anda, mengunduh executable Bun yang sesuai, dan biasanya menginstalnya ke ~/.bun/bin
. Ini juga mencoba memperbarui file konfigurasi shell Anda (seperti .zshrc
, .bashrc
, atau .bash_profile
) untuk menambahkan ~/.bun/bin
ke PATH
sistem Anda, membuat perintah bun
tersedia secara global. Anda mungkin perlu me-restart sesi terminal Anda atau secara manual me-source file konfigurasi shell Anda (misalnya, source ~/.zshrc
) agar perubahan segera berlaku.
Jika Anda mengalami masalah izin atau lebih suka tidak mengirimkan langsung ke bash
, Anda dapat mengunduh skrip terlebih dahulu dan memeriksanya sebelum menjalankan:
curl -fsSL https://bun.sh/install -o install.sh
# Periksa install.sh jika diinginkan
bash install.sh
Metode Instalasi Lainnya:
- NPM: Meskipun terutama ditujukan sebagai alat mandiri, Anda juga dapat menginstal Bun secara global melalui npm, yang mungkin nyaman di lingkungan di mana Node.js dan npm sudah ada:
npm install -g bun
- Docker: Gambar Docker Bun resmi tersedia di Docker Hub, menyediakan lingkungan terisolasi dengan Bun yang sudah diinstal sebelumnya. Ini berguna untuk alur kerja pengembangan dan deployment dalam kontainer. Anda dapat menemukan berbagai gambar berdasarkan distribusi OS dasar yang berbeda (seperti Debian, Alpine) dan tag yang sesuai dengan versi Bun tertentu.
docker run --rm --init --ulimit memlock=-1:-1 oven/bun:latest bun --version
- Windows: Dukungan Windows native untuk Bun masih dianggap eksperimental tetapi sedang aktif dikembangkan. Cara yang disarankan untuk menggunakan Bun di Windows saat ini adalah melalui WSL. Namun, build Windows langsung mulai tersedia, dan proses instalasi mungkin melibatkan pengunduhan arsip
.zip
dan penambahan lokasi executable secara manual kePATH
sistem. Periksa dokumentasi resmi Bun untuk status terbaru dan instruksi untuk instalasi Windows native. - Homebrew (macOS): Jika Anda menggunakan Homebrew di macOS, Anda dapat menginstal Bun melalui tap-nya:
brew tap oven-sh/bun
brew install bun
Verifikasi:
Setelah terinstal, buka jendela terminal baru dan verifikasi instalasi dengan memeriksa versinya:
bun --version
Ini akan menampilkan nomor versi yang terinstal, mengonfirmasi bahwa Bun siap digunakan. Anda juga dapat menjalankan bun --help
untuk melihat daftar perintah dan opsi yang tersedia.
Jalankan Bun Anda untuk Pertama Kali
Mari kita selami menulis dan menjalankan program sederhana dengan Bun. Salah satu tugas paling umum adalah membuat server HTTP. Bun menyediakan API bawaan yang sangat dioptimalkan untuk tujuan ini: Bun.serve
.
Buat file baru bernama server.js
(atau server.ts
, karena Bun menangani keduanya):
// server.ts
// Bun.serve memulai server HTTP
const server = Bun.serve({
// Tentukan port untuk didengarkan.
// Default ke process.env.PORT || 3000
port: 3000,
// Fungsi 'fetch' adalah handler permintaan inti.
// Ini menerima objek Request standar dan harus mengembalikan objek Response (atau Promise yang menyelesaikannya).
fetch(request: Request): Response {
// Buat objek Response API Web standar
return new Response("Welcome to Bun!");
},
});
// Log pesan yang menunjukkan server sedang berjalan
console.log(`Listening on http://localhost:${server.port}`);
Cuplikan kode ini melakukan hal berikut:
- Ini memanggil
Bun.serve
, fungsi utama untuk membuat server HTTP di Bun. - Ini meneruskan objek konfigurasi, menentukan
port
(3000 dalam kasus ini). - Bagian krusial adalah fungsi
fetch
. Fungsi ini dipanggil untuk setiap permintaan HTTP yang masuk. Ini selaras dengan pola handler peristiwa fetch Service Worker, menerima objekRequest
standar. - Di dalam
fetch
, kita membangun dan mengembalikan objekResponse
standar. Di sini, kita hanya mengembalikan teks biasa "Welcome to Bun!". - Terakhir, kita mencatat pesan konfirmasi ke konsol, termasuk port aktual yang didengarkan oleh server (dapat diakses melalui
server.port
).
Untuk menjalankan server ini, buka terminal Anda di direktori tempat Anda menyimpan file dan eksekusi:
bun run server.ts
Atau, jika Anda menyimpannya sebagai server.js
:
bun run server.js
Bun akan mengeksekusi skrip. Jika Anda menggunakan TypeScript (server.ts
), transpiler internal Bun akan menangani konversi ke JavaScript secara langsung sebelum eksekusi. Anda akan melihat pesan "Listening on http://localhost:3000".
Sekarang, buka browser web Anda dan navigasikan ke http://localhost:3000
. Anda akan melihat teks "Welcome to Bun!" ditampilkan.
Untuk menghentikan server, kembali ke terminal Anda dan tekan Ctrl + C
.
Contoh sederhana ini menunjukkan kemudahan menyiapkan server dasar dan menjalankan kode (termasuk TypeScript) langsung dengan Bun, menampilkan sifat terintegrasinya dan ketergantungan pada API Standar Web seperti Request
dan Response
.
Apa Dukungan Native TypeScript di Bun
Salah satu keunggulan paling signifikan dari Bun, terutama bagi pengembang yang sudah menggunakan atau ingin mengadopsi TypeScript, adalah dukungan kelas satu, siap pakainya. Berbeda dengan Node.js, di mana menjalankan TypeScript biasanya memerlukan pra-kompilasi menggunakan kompiler TypeScript (tsc
) atau menggunakan loader/register seperti ts-node
atau tsx
, Bun menanganinya secara native dan transparan.
Cara Kerjanya:
Ketika Anda meminta Bun untuk menjalankan file .ts
atau .tsx
(misalnya, bun run myscript.ts
), ia secara otomatis memanggil transpiler internalnya. Transpiler ini ditulis dalam kode native (Zig) dan sangat cepat. Tugasnya adalah:
- Menghapus Tipe: Menghapus anotasi tipe TypeScript, interface, enum, dll., karena ini bukan bagian dari eksekusi JavaScript standar.
- Mengubah Sintaks: Mengonversi sintaks spesifik TypeScript (seperti penggunaan
enum
tertentu atau sintaks dekorator yang lebih lama jika dikonfigurasi) menjadi JavaScript yang setara. - Menangani JSX: Mengubah sintaks JSX (digunakan dalam file
.tsx
dan.jsx
) menjadi panggilan fungsi JavaScript standar (biasanyaReact.createElement
atau setara runtime JSX yang dikonfigurasi).
Manfaat utamanya adalah ini terjadi secara langsung selama proses eksekusi (bun run
) atau bundling (bun build
). Tidak ada langkah build terpisah dan eksplisit yang diperlukan hanya untuk menjalankan kode TypeScript Anda selama pengembangan.
Contoh:
Pertimbangkan file TypeScript ini (greet.ts
):
// greet.ts
interface User {
name: string;
id: number;
}
function greetUser(user: User): void {
console.log(`Hello, ${user.name} (ID: ${user.id})!`);
}
const myUser: User = { name: "Bun Developer", id: 123 };
greetUser(myUser);
// Anda bahkan dapat menggunakan fitur modern yang didukung Bun
const message = `Bun version: ${Bun.version}`;
console.log(message);
Anda dapat menjalankan ini secara langsung:
bun run greet.ts
Bun akan mentranspilasinya secara internal dan mengeksekusi JavaScript yang dihasilkan, menghasilkan output seperti:
Hello, Bun Developer (ID: 123)!
Bun version: 1.x.y
Dukungan JSX:
Demikian pula, jika Anda memiliki file .tsx
dengan JSX:
// component.tsx
// Dengan asumsi Anda telah mengonfigurasi JSX (default Bun seringkali berfungsi dengan React)
function MyComponent({ name }: { name: string }) {
return <div className="greeting">Hello, {name}!</div>;
}
// CATATAN: Menjalankan ini secara langsung tidak akan me-render HTML,
// ini hanya menunjukkan struktur JS yang ditranspilasi.
// Anda biasanya akan menggunakannya dalam aplikasi atau framework yang lebih besar.
console.log("Mensimulasikan pembuatan komponen (struktur output yang ditranspilasi):");
// Output aktual tergantung pada pengaturan transformasi JSX,
// tetapi itu akan menjadi objek/panggilan fungsi JavaScript.
Menjalankan bun run component.tsx
akan mengeksekusi file, mentranspilasi JSX menjadi JavaScript.
Konfigurasi (tsconfig.json
):
Bun menghormati file tsconfig.json
untuk opsi konfigurasi yang memengaruhi transpilation. Meskipun tidak melakukan pemeriksaan tipe penuh seperti tsc
(Bun berfokus pada kecepatan eksekusi dan transpilation), ia membaca tsconfig.json
untuk memahami pengaturan seperti:
jsx
: ("react-jsx"
,"react"
, dll.) Bagaimana JSX harus diubah.jsxImportSource
: Modul untuk mengimpor fungsi pembantu JSX dari (misalnya,"react"
).experimentalDecorators
,emitDecoratorMetadata
: Dukungan untuk dekorator.paths
,baseUrl
: Pemetaan jalur modul untuk alias impor kustom.target
,module
: Meskipun Bun mengelola eksekusi, ini terkadang dapat memengaruhi detail transpilation kecil.strict
,strictNullChecks
, dll.: Ini terutama memengaruhi pemeriksaan tipe (yang tidak dilakukan Bun selamarun
), tetapi beberapa perilaku emit JavaScript terkait mungkin terpengaruh.
Jika tidak ada tsconfig.json
yang ditemukan, Bun menggunakan pengaturan default yang masuk akal.
Integrasi mulus ini membuat memulai proyek TypeScript dengan Bun sangat sederhana dan cepat, menurunkan hambatan masuk dan mempercepat siklus pengembangan.
Mari Bicara Tentang API Spesifik Bun
Meskipun Bun sangat menekankan kompatibilitas dengan API Standar Web dan Node.js, ia juga memperkenalkan serangkaian API bawaannya sendiri yang dioptimalkan di bawah objek global Bun
. API ini seringkali menyediakan alternatif berperforma tinggi atau pembungkus yang nyaman untuk tugas-tugas umum yang memanfaatkan kemampuan kode native Bun.
Berikut adalah sekilas beberapa API Bun.*
utama:
Bun.serve({...})
: Seperti yang terlihat di Quickstart, ini adalah landasan untuk membangun server HTTP dan WebSocket yang sangat berperforma. Ini menawarkan konfigurasi yang disederhanakan dan menggunakan tanda tangan handlerfetch
standar. (Dibahas secara rinci nanti).Bun.file(path)
: Membuat objekBunFile
, yang merupakan referensi malas ke file di disk. Ini menyediakan metode yang sangat dioptimalkan untuk membaca konten file dalam berbagai format (.text()
,.json()
,.arrayBuffer()
,.stream()
) hanya saat dibutuhkan. Ini seringkali jauh lebih cepat daripada ekuivalennode:fs
.Bun.write(path, data)
: Pasangan dariBun.file
, digunakan untuk menulis data ke file secara efisien. Ini menerima berbagai tipe data (string, Blob, Buffer,BunFile
lainnya) dan melakukan penulisan atomik secara default.Bun.build({...})
: Menyediakan akses terprogram ke bundler bawaan Bun, yang kompatibel dengan API esbuild. Memungkinkan bundling JavaScript/TypeScript untuk browser atau runtime lain langsung dari dalam skrip Bun.Bun.spawn({...})
/Bun.spawnSync({...})
: Menjalankan perintah eksternal sebagai proses anak, mirip denganchild_process
Node.js. Menawarkan API streaming asynchronous dan versi sinkron yang lebih sederhana, dioptimalkan untuk overhead rendah.Bun.Transpiler({...})
: Akses terprogram langsung ke transpiler internal Bun yang cepat untuk mengonversi TypeScript/JSX ke JavaScript tanpa bundling penuh.Bun.password.hash(...)
/Bun.password.verify(...)
: Fungsi yang aman dan mudah digunakan untuk hashing dan memverifikasi kata sandi menggunakan algoritma standar industri seperti Argon2id (direkomendasikan) dan bcrypt. Menghindari kebutuhan akan pustaka eksternal.Bun.env
: Objek yang menyediakan akses ke variabel lingkungan, mirip denganprocess.env
, tetapi berpotensi menawarkan akses yang lebih cepat dalam beberapa skenario.Bun.version
: String yang berisi versi Bun yang sedang berjalan.Bun.revision
: String yang berisi hash commit Git dari build Bun yang sedang berjalan.Bun.sleep(ms)
/Bun.sleepSync(ms)
: Fungsi untuk menjeda eksekusi selama durasi tertentu.Bun.gc()
: Memicu pengumpulan sampah secara manual (gunakan dengan hemat, terutama untuk debugging/benchmarking).Bun.resolveSync(specifier, parentPath)
/Bun.resolve(specifier, parentPath)
: Melakukan resolusi modul gaya Node.js secara terprogram untuk menemukan jalur absolut modul.
API ini mewakili upaya Bun untuk menyediakan solusi bawaan yang dioptimalkan untuk tugas-tugas pengembangan umum, mengurangi ketergantungan pada dependensi eksternal dan memanfaatkan kecepatan inti native-nya.
API Web di Bun
Pilihan desain fundamental di Bun adalah komitmen kuatnya untuk mengimplementasikan API Web standar. Di mana pun API standar ada untuk tugas tertentu (terutama untuk penanganan jaringan dan data), Bun lebih memilih untuk mengimplementasikan standar tersebut daripada menciptakan API proprietary atau hanya mengandalkan konvensi Node.js.
Pendekatan ini menawarkan beberapa keuntungan signifikan:
- Portabilitas Kode: Kode yang ditulis menggunakan API Web standar seringkali dapat digunakan kembali di berbagai lingkungan JavaScript – browser, Node.js (yang juga semakin mengadopsi standar Web), Deno, Cloudflare Workers, dan Bun – dengan lebih sedikit modifikasi.
- Keterbiasaan: Pengembang yang sudah familiar dengan API browser dapat memanfaatkan pengetahuan tersebut saat bekerja dengan Bun, mengurangi kurva pembelajaran.
- Tahan Masa Depan: Penyelarasan dengan standar yang ditetapkan oleh badan seperti WHATWG dan W3C umumnya mengarah pada API yang lebih stabil dan didukung secara luas dalam jangka panjang.
- Kinerja: Implementasi native Bun dari API Web ini sangat dioptimalkan untuk runtime-nya.
API Standar Web utama yang diimplementasikan di Bun meliputi:
Fetch API:
fetch()
: Fungsi global untuk membuat permintaan HTTP(S).Request
: Merepresentasikan permintaan HTTP.Response
: Merepresentasikan respons HTTP.Headers
: Merepresentasikan header HTTP.
URL API:
URL
: Untuk mem-parsing dan memanipulasi URL.URLSearchParams
: Untuk bekerja dengan parameter query URL.
Streams API:
ReadableStream
: Merepresentasikan sumber data yang dapat dibaca secara asynchronous. Digunakan untuk body permintaan/respons, pembacaan file, dll.WritableStream
: Merepresentasikan tujuan data yang dapat ditulis secara asynchronous. Digunakan untuk body permintaan, penulisan file, dll.TransformStream
: Stream dupleks yang mengubah data saat melewatinya (misalnya, kompresi, encoding).
Encoding API:
TextEncoder
: Mengodekan string menjadiUint8Array
(biasanya UTF-8).TextDecoder
: MendekodeUint8Array
menjadi string.
Blob API:
Blob
: Merepresentasikan data mentah yang tidak dapat diubah, sering digunakan untuk objek seperti file.File
: MemperluasBlob
untuk merepresentasikan file, termasuk metadata seperti nama dan tanggal modifikasi terakhir. (Sering dibuat melaluiBun.file().slice()
atau dari data form).
FormData API:
FormData
: Untuk membangun kumpulan pasangan kunci/nilai, sering digunakan untuk mengirimkan data form dalam permintaanfetch
.
WebSocket API:
WebSocket
: API sisi klien untuk membangun koneksi WebSocket. (Penanganan sisi server terintegrasi ke dalamBun.serve
).
Timers:
setTimeout
,setInterval
,clearTimeout
,clearInterval
: Fungsi standar untuk menjadwalkan eksekusi kode.
Console API:
console.log
,console.error
,console.warn
, dll.: Fungsi logging standar.
Crypto API:
crypto.subtle
: Menyediakan akses ke primitif kriptografi tingkat rendah (hashing, penandatanganan, enkripsi).crypto.randomUUID()
: Menghasilkan UUID v4.crypto.getRandomValues()
: Menghasilkan angka acak yang kuat secara kriptografi.
Performance API:
performance.now()
: Menyediakan timestamp resolusi tinggi untuk pengukuran kinerja.
Dengan menyediakan implementasi yang kuat dan berperforma dari API Web penting ini, Bun memposisikan dirinya sebagai runtime modern yang cocok untuk membangun server web, API, dan aplikasi berpusat jaringan lainnya menggunakan antarmuka standar yang familiar.
Server HTTP Bun, Dijelaskan
Cara utama untuk membuat server web di Bun adalah melalui API Bun.serve
. Ini dirancang untuk kinerja luar biasa dan kemudahan penggunaan, berintegrasi secara mulus dengan API Web standar seperti Request
, Response
, dan fetch
.
Konsep Inti:
Fungsi Bun.serve
mengambil objek konfigurasi dan mengembalikan objek Server
. Bagian terpenting dari konfigurasi adalah fungsi fetch
.
import { type Server } from "bun";
const server: Server = Bun.serve({
port: 8080, // Port untuk didengarkan
hostname: "0.0.0.0", // Antarmuka jaringan untuk diikat (0.0.0.0 untuk semua)
// fetch: Jantung server - menangani permintaan masuk
async fetch(req: Request, server: Server): Promise<Response> {
// req adalah objek Request API Web standar
// server adalah referensi ke instance Server itu sendiri
const url = new URL(req.url);
// Contoh Routing Dasar
if (url.pathname === "/") {
return new Response("Homepage");
}
if (url.pathname === "/about") {
return new Response("About Us page");
}
if (url.pathname === "/greet" && req.method === "GET") {
const name = url.searchParams.get("name") || "World";
return new Response(`Hello, ${name}!`);
}
if (url.pathname === "/data" && req.method === "POST") {
try {
const data = await req.json(); // Baca body permintaan sebagai JSON
console.log("Received data:", data);
return new Response(JSON.stringify({ received: data }), {
headers: { 'Content-Type': 'application/json' }
});
} catch (e) {
return new Response("Invalid JSON body", { status: 400 });
}
}
// Default 404 Not Found
return new Response("Page Not Found", { status: 404 });
},
// error: Handler opsional untuk kesalahan yang terjadi *di luar* handler fetch
error(error: Error): Response | Promise<Response> {
console.error("[Server Error]", error);
return new Response("Something went wrong!", { status: 500 });
},
// development: Setel ke true untuk halaman kesalahan pengembangan yang membantu (default: !process.env.NODE_ENV=production)
development: true,
// Opsi lain seperti 'websocket', 'tls' ada untuk kasus penggunaan lanjutan
});
console.log(`Bun server listening on http://${server.hostname}:${server.port}`);
// Anda dapat berinteraksi dengan objek server:
// server.stop() // Menghentikan server
// server.reload({...}) // Memperbarui konfigurasi server (misalnya, handler fetch) secara dinamis
Fitur Utama:
- Kinerja:
Bun.serve
dibangun di atas implementasi server HTTP kustom Bun yang sangat dioptimalkan yang ditulis dalam Zig. Ini mampu menangani jumlah permintaan per detik yang sangat tinggi dengan latensi rendah dan konsumsi sumber daya dibandingkan dengan banyak framework Node.js. - Handler
fetch
: Menggunakan tanda tangan standar(Request) => Response | Promise<Response>
membuat logika inti familiar bagi siapa pun yang pernah bekerja dengan Service Workers, Cloudflare Workers, atau framework web modern lainnya. Ini mendorong penggunaan objekRequest
danResponse
standar. - Objek Permintaan: Parameter
req
menyediakan akses ke properti dan metodeRequest
standar:req.url
,req.method
,req.headers
,req.json()
,req.text()
,req.arrayBuffer()
,req.formData()
,req.body
(sebuahReadableStream
). - Objek Respons: Anda membuat dan mengembalikan objek
Response
standar, memungkinkan Anda mengatur body (string, Buffer, Blob, Stream, dll.), kode status, dan header dengan mudah. - Penanganan Kesalahan: Fungsi
error
opsional menyediakan tempat terpusat untuk menangkap kesalahan yang terjadi sebelum atau selama pemrosesan awal permintaan oleh server itu sendiri (misalnya, kegagalan handshake TLS, permintaan yang salah format), atau kesalahan yang dilemparkan secara sinkron di luartry...catch
handlerfetch
. Kesalahan dalam handlerfetch
asynchronous biasanya harus ditangkap di sana. - Streaming: Body permintaan dan respons dapat di-stream menggunakan API
ReadableStream
danWritableStream
standar, penting untuk menangani unggahan atau unduhan besar secara efisien. - Pemuatan Ulang Dinamis: Metode
server.reload()
memungkinkan pembaruan opsi server, termasuk handlerfetch
danerror
, tanpa memerlukan restart server penuh, yang berguna untuk pengaturan hot module replacement (HMR).
Bun.serve
menyediakan dasar yang kuat namun sederhana untuk membangun aplikasi web dan API di Bun, memprioritaskan kecepatan dan kepatuhan terhadap standar web.
Klien Bun Fetch
Melengkapi API server, Bun menyediakan fungsi fetch
global untuk membuat permintaan HTTP(S) keluar. Implementasi ini sangat mematuhi standar WHATWG Fetch, membuatnya familiar bagi pengembang web dan memastikan konsistensi dengan fungsi fetch
yang digunakan dalam Bun.serve
. Implementasi native Bun memastikan kinerja tinggi untuk tugas jaringan sisi klien.
Membuat Permintaan:
Penggunaan dasar melibatkan pemanggilan fetch
dengan URL dan secara opsional objek konfigurasi:
async function makeRequests() {
const url = "https://httpbin.org"; // Layanan yang berguna untuk menguji permintaan HTTP
// --- Permintaan GET Dasar ---
console.log("--- Permintaan GET ---");
try {
const getResponse = await fetch(`${url}/get?param1=value1`);
console.log(`Status: ${getResponse.status} ${getResponse.statusText}`);
// Periksa apakah permintaan berhasil (status 200-299)
if (!getResponse.ok) {
throw new Error(`Kesalahan HTTP! status: ${getResponse.status}`);
}
// Akses header
console.log("Header Content-Type:", getResponse.headers.get('content-type'));
// Baca body respons sebagai JSON
const getData = await getResponse.json();
console.log("JSON Respons:", getData.args); // httpbin.org/get mengembalikan parameter query di 'args'
} catch (error) {
console.error("Permintaan GET gagal:", error);
}
// --- Permintaan POST dengan body JSON ---
console.log("\n--- Permintaan POST (JSON) ---");
try {
const postData = { name: "Bun", type: "Runtime" };
const postResponse = await fetch(`${url}/post`, {
method: "POST",
headers: {
// Menunjukkan kita mengirim JSON
"Content-Type": "application/json",
"Accept": "application/json", // Menunjukkan kita lebih suka JSON kembali
"X-Custom-Header": "BunFetchExample",
},
// Body harus di-stringifikasi untuk JSON
body: JSON.stringify(postData),
});
if (!postResponse.ok) {
throw new Error(`Kesalahan HTTP! status: ${postResponse.status}`);
}
const postResult = await postResponse.json();
console.log("JSON Respons POST:", postResult.json); // httpbin.org/post mengembalikan JSON yang diposting di 'json'
} catch (error) {
console.error("Permintaan POST gagal:", error);
}
// --- Permintaan dengan Timeout ---
console.log("\n--- Permintaan GET dengan Timeout ---");
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 2000); // Batalkan setelah 2 detik
const timeoutResponse = await fetch(`${url}/delay/5`, { // Endpoint ini menunggu 5 detik
signal: controller.signal // Teruskan AbortSignal
});
clearTimeout(timeoutId); // Hapus timeout jika fetch selesai lebih cepat
console.log("Permintaan timeout berhasil (tidak terduga untuk /delay/5)");
} catch (error: any) {
// AbortError dilemparkan saat sinyal membatalkan
if (error.name === 'AbortError') {
console.log("Fetch dibatalkan karena timeout, seperti yang diharapkan.");
} else {
console.error("Permintaan timeout gagal:", error);
}
}
}
await makeRequests();
Fitur dan Opsi Utama:
API Standar: Menggunakan tanda tangan fetch(url, options)
yang familiar.
Metode: Mendukung semua metode HTTP standar (GET
, POST
, PUT
, DELETE
, PATCH
, HEAD
, OPTIONS
). Ditentukan melalui opsi method
.
Header: Header diatur menggunakan opsi headers
, yang dapat berupa objek Headers
atau objek biasa key-value sederhana.
Body Permintaan: Opsi body
menerima berbagai tipe:
string
: Dikirim sebagai teks (umum untuk JSON, XML, plain text).ArrayBuffer
/TypedArray
: Dikirim sebagai data biner.Blob
/File
: Dikirim sebagai data biner, seringkali denganContent-Type
yang sesuai.ReadableStream
: Mengalirkan konten body, cocok untuk unggahan besar.URLSearchParams
: Secara otomatis mengaturContent-Type
keapplication/x-www-form-urlencoded
.FormData
: Secara otomatis mengaturContent-Type
kemultipart/form-data
.
Penanganan Respons: Panggilan fetch
mengembalikan Promise
yang menyelesaikan ke objek Response
.
response.ok
: Boolean yang menunjukkan status HTTP yang berhasil (200-299).response.status
: Kode status HTTP (misalnya, 200, 404).response.statusText
: Pesan status HTTP (misalnya, "OK", "Not Found").response.headers
: ObjekHeaders
untuk mengakses header respons.- Metode Pembacaan Body:
response.json()
,response.text()
,response.arrayBuffer()
,response.blob()
,response.formData()
. Ini mengembalikan Promise. response.body
: SebuahReadableStream
untuk mengalirkan body respons.
Timeout & Pembatalan: Gunakan AbortController
dan AbortSignal
untuk mengimplementasikan timeout atau membatalkan permintaan secara manual. Teruskan signal
ke opsi fetch
.
Pengalihan: Dikontrol oleh opsi redirect
('follow'
, 'manual'
, 'error'
). Default ke 'follow'
.
- Caching: Dikontrol oleh opsi
cache
(misalnya,'no-store'
,'reload'
).
fetch
Bun menyediakan cara yang berperforma dan sesuai standar untuk berinteraksi dengan sumber daya HTTP, berintegrasi secara mulus ke dalam ekosistem Bun.
WebSocket Bun
WebSocket menyediakan cara untuk membangun saluran komunikasi persisten, dua arah antara klien dan server melalui satu koneksi TCP. Bun menawarkan dukungan luar biasa untuk WebSocket, baik untuk membuat klien WebSocket maupun untuk menangani koneksi WebSocket di sisi server dalam Bun.serve
.
1. Klien WebSocket:
Bun mengimplementasikan API WebSocket
browser standar untuk membuat koneksi klien.
// websocket-client.ts
const wsUrl = "wss://ws.postman-echo.com/raw"; // Server echo publik
console.log(`Menghubungkan klien ke ${wsUrl}...`);
const socket = new WebSocket(wsUrl);
// Event: Koneksi berhasil dibuka
socket.addEventListener("open", (event) => {
console.log("[Klien] Koneksi WebSocket berhasil dibuat!");
socket.send("Halo dari klien Bun!");
// Kirim data biner setelah jeda singkat
setTimeout(() => {
const binaryData = new TextEncoder().encode("Data biner Bun");
console.log("[Klien] Mengirim biner:", binaryData);
socket.send(binaryData);
}, 500);
// Tutup koneksi setelah beberapa waktu
setTimeout(() => {
console.log("[Klien] Menutup koneksi...");
socket.close(1000, "Klien selesai menguji"); // 1000 = Penutupan normal
}, 2000);
});
// Event: Pesan diterima dari server
socket.addEventListener("message", async (event) => {
// event.data bisa berupa string, Blob, atau ArrayBuffer
let messageContent: string | Uint8Array;
if (typeof event.data === "string") {
messageContent = event.data;
console.log(`[Klien] Menerima string: "${messageContent}"`);
} else if (event.data instanceof Blob) {
// Bun sering menerima data biner sebagai Blob dari API WebSocket
const arrayBuffer = await event.data.arrayBuffer();
messageContent = new Uint8Array(arrayBuffer);
console.log(`[Klien] Menerima biner (Blob):`, messageContent, `(${new TextDecoder().decode(messageContent)})`);
} else if (event.data instanceof ArrayBuffer) {
messageContent = new Uint8Array(event.data);
console.log(`[Klien] Menerima biner (ArrayBuffer):`, messageContent, `(${new TextDecoder().decode(messageContent)})`);
} else {
console.log("[Klien] Menerima tipe pesan tidak dikenal:", event.data);
}
});
// Event: Terjadi kesalahan (masalah jaringan, dll.)
socket.addEventListener("error", (event) => {
// Objek event seringkali kurang detail spesifik. Periksa log konsol/jaringan.
console.error("[Klien] Kesalahan WebSocket:", event.type);
});
// Event: Koneksi ditutup
socket.addEventListener("close", (event) => {
console.log(
`[Klien] WebSocket ditutup. Kode: ${event.code}, Alasan: "${event.reason}", Bersih: ${event.wasClean}`
);
// Keluar dari skrip dengan bersih setelah socket ditutup
process.exit(0);
});
// Tetap hidup sebentar untuk event, keluar ditangani di listener 'close'
// setInterval(() => {}, 1000);
Jalankan ini dengan bun run websocket-client.ts
. Ini terhubung ke server echo, mengirim pesan, menerimanya kembali, lalu menutup.
2. Server WebSocket (Integrasi Bun.serve
):
Menangani koneksi WebSocket di server dilakukan dengan menambahkan properti websocket
ke objek konfigurasi Bun.serve
. Properti ini berisi fungsi handler untuk berbagai peristiwa siklus hidup WebSocket.
// websocket-server.ts
import { type ServerWebSocket, type WebSocketHandler } from "bun";
console.log("Memulai server WebSocket...");
// Definisikan objek handler WebSocket
const wsHandler: WebSocketHandler<{ authToken: string }> = {
// open(ws): Dipanggil saat koneksi WebSocket baru dibuat.
// Panggilan server.upgrade() di 'fetch' diperlukan terlebih dahulu.
open(ws: ServerWebSocket<{ authToken: string }>) {
console.log(`[Server] Koneksi dibuka. Token: ${ws.data.authToken}`);
ws.send("Selamat datang di server WebSocket Bun!");
// Berlangganan topik pub/sub
ws.subscribe("the-group-chat");
// Publikasikan pesan ke topik (termasuk pengguna baru)
ws.publish("the-group-chat", `Pengguna dengan token ${ws.data.authToken} bergabung.`);
},
// message(ws, message): Dipanggil saat pesan diterima dari klien.
// 'message' bisa berupa string atau Uint8Array (Buffer).
message(ws: ServerWebSocket<{ authToken: string }>, message: string | Buffer) {
const messageString = message.toString(); // Tangani string/buffer
console.log(`[Server] Menerima dari token ${ws.data.authToken}: ${messageString}`);
// Echo kembali pesan yang diawali dengan token
// ws.send(`[${ws.data.authToken}] Anda mengirim: ${messageString}`);
// Publikasikan pesan ke semua orang di ruang obrolan (termasuk pengirim)
server.publish("the-group-chat", `[${ws.data.authToken}] ${messageString}`);
},
// close(ws, code, reason): Dipanggil saat koneksi WebSocket ditutup.
close(ws: ServerWebSocket<{ authToken: string }>, code: number, reason: string) {
const goodbyeMessage = `[Server] Koneksi ditutup. Token: ${ws.data.authToken}, Kode: ${code}, Alasan: ${reason}`;
console.log(goodbyeMessage);
// Berhenti berlangganan dan beri tahu yang lain
ws.unsubscribe("the-group-chat");
server.publish("the-group-chat", `Pengguna dengan token ${ws.data.authToken} keluar.`);
},
// drain(ws): Opsional. Dipanggil saat jumlah buffer socket berkurang,
// menunjukkan bahwa ia siap menerima lebih banyak data setelah backpressure.
// Berguna untuk mengelola kontrol aliran saat mengirim data dalam jumlah besar.
// drain(ws: ServerWebSocket<{ authToken: string }>) {
// console.log(`[Server] Peristiwa drain untuk token ${ws.data.authToken}`);
// },
};
// Buat server HTTP dengan penanganan WebSocket
const server = Bun.serve<{ authToken: string }>({ // Teruskan generik untuk tipe ws.data
port: 8081,
// Handler fetch perlu menangani permintaan upgrade HTTP -> WebSocket
fetch(req: Request, server: Server): Response | undefined {
const url = new URL(req.url);
// Periksa apakah permintaan mencoba melakukan upgrade ke WebSocket
if (url.pathname === "/ws") {
// Ekstrak beberapa data (misalnya, token auth) untuk diteruskan ke konteks WebSocket
const token = req.headers.get("sec-websocket-protocol") || "anonymous"; // Contoh: gunakan header protokol untuk token
const success = server.upgrade(req, {
// Objek data dilampirkan ke instance ws (ws.data)
// tersedia di semua handler websocket untuk koneksi ini.
// HARUS dapat diserialisasi JSON jika menggunakan di seluruh worker/proses nanti.
data: {
authToken: token,
},
// headers: new Headers({ 'X-Custom-Response-Header': 'UpgradeValue' }) // Opsional: Tambahkan header ke respons 101
});
if (success) {
// server.upgrade() menangani respons 101 Switching Protocols.
// Kembalikan undefined dari handler fetch setelah upgrade berhasil.
return undefined;
} else {
// Upgrade gagal (misalnya, header permintaan tidak valid)
return new Response("Upgrade WebSocket gagal", { status: 400 });
}
}
// Tangani permintaan HTTP biasa di jalur lain
return new Response("Bukan endpoint WebSocket. Coba /ws", { status: 404 });
},
// Lampirkan objek handler WebSocket
websocket: wsHandler,
error(error: Error): Response | Promise<Response> {
console.error("[Server Error]", error);
return new Response("Kesalahan server", { status: 500 });
},
});
console.log(`Server WebSocket Bun mendengarkan di ws://localhost:${server.port}/ws`);
Konsep Utama Server:
Permintaan Upgrade: Koneksi WebSocket dimulai sebagai permintaan GET HTTP standar dengan header spesifik (Upgrade: websocket
, Connection: Upgrade
, Sec-WebSocket-Key
, dll.). Handler fetch
harus mendeteksi permintaan ini.
server.upgrade(req, { data: ... })
: Metode krusial ini, dipanggil dalam handlerfetch
, mencoba menyelesaikan handshake WebSocket. Jika berhasil, ia mengembalikantrue
, dan Bun mengambil alih koneksi menggunakan handlerwebsocket
. Jika gagal, ia mengembalikanfalse
. Anda harus mengembalikanundefined
darifetch
setelah upgrade berhasil.- Objek Handler
websocket
: Berisi fungsiopen
,message
,close
, dandrain
untuk mengelola siklus hidup WebSocket untuk klien yang terhubung. ServerWebSocket<T>
: Tipe yang merepresentasikan koneksi WebSocket sisi server. GenerikT
mendefinisikan tipe objekws.data
.ws.data
: Objek yang terkait dengan setiap koneksi, diinisialisasi oleh propertidata
dalam opsiserver.upgrade
. Berguna untuk menyimpan state spesifik koneksi (seperti ID pengguna, token auth).
Pub/Sub: Bun menyertakan kemampuan publish/subscribe bawaan yang efisien untuk WebSocket:
ws.subscribe("topic-name")
: Berlangganan koneksi ke topik.ws.unsubscribe("topic-name")
: Berhenti berlangganan koneksi.ws.publish("topic-name", message)
: Mengirim pesan ke semua koneksi yang berlangganan topik kecuali pengirimws
.server.publish("topic-name", message)
: Mengirim pesan ke semua koneksi yang berlangganan topik (berguna untuk siaran di seluruh sistem).
Backpressure: Metode ws.send()
mengembalikan jumlah byte yang di-buffer. Jika nilai ini bertambah besar, Anda mungkin mengirim lebih cepat daripada yang dapat diterima klien. Peristiwa drain
memberi sinyal saat buffer telah menyusut, memungkinkan Anda melanjutkan pengiriman dengan aman.
Dukungan WebSocket terintegrasi Bun menyediakan cara yang berperforma dan nyaman untuk membangun fitur real-time ke dalam aplikasi, lengkap dengan fungsionalitas pub/sub bawaan.
Panduan ini telah membahas aspek fundamental Bun, mulai dari filosofi inti dan instalasinya hingga API spesifiknya seperti Bun.serve
, Bun.file
, Bun.build
, dan implementasinya dari Standar Web krusial seperti fetch
dan WebSocket
. Dengan menggabungkan kecepatan, alat terintegrasi, dukungan TypeScript/JSX native, dan fokus pada standar, Bun menawarkan lingkungan yang menarik dan produktif untuk pengembangan JavaScript dan TypeScript modern.
Ingin platform All-in-One yang terintegrasi untuk Tim Pengembang Anda bekerja sama dengan produktivitas maksimum?
Apidog memenuhi semua permintaan Anda, dan menggantikan Postman dengan harga yang jauh lebih terjangkau!