Apidog

Platform Pengembangan API Kolaboratif All-in-one

Desain API

Dokumentasi API

Debug API

Mocking API

Pengujian Otomatis API

Memulai dengan Bun API

Mark Ponomarev

Mark Ponomarev

Updated on May 4, 2025

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 alat Pengujian API hebat yang menghasilkan Dokumentasi API yang indah?

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!
button

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:

  1. Alat Terintegrasi: Perintah bun itu sendiri bertindak sebagai titik masuk untuk berbagai fungsi. bun run mengeksekusi skrip yang ditentukan dalam package.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, dan bunx mengeksekusi paket tanpa menginstalnya secara eksplisit. Integrasi ini menyederhanakan alur kerja dengan mengurangi jumlah alat pengembangan yang berbeda yang dibutuhkan.
  2. 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 melibatkan tsc atau Babel untuk banyak skenario pengembangan umum, merampingkan proses pengaturan.
  3. 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 dan require sebagian besar secara bergantian dan memanfaatkan jutaan paket CJS yang ada yang tersedia di npm.
  4. 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.
  5. 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 ke PATH 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:

  1. Ini memanggil Bun.serve, fungsi utama untuk membuat server HTTP di Bun.
  2. Ini meneruskan objek konfigurasi, menentukan port (3000 dalam kasus ini).
  3. Bagian krusial adalah fungsi fetch. Fungsi ini dipanggil untuk setiap permintaan HTTP yang masuk. Ini selaras dengan pola handler peristiwa fetch Service Worker, menerima objek Request standar.
  4. Di dalam fetch, kita membangun dan mengembalikan objek Response standar. Di sini, kita hanya mengembalikan teks biasa "Welcome to Bun!".
  5. 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:

  1. Menghapus Tipe: Menghapus anotasi tipe TypeScript, interface, enum, dll., karena ini bukan bagian dari eksekusi JavaScript standar.
  2. Mengubah Sintaks: Mengonversi sintaks spesifik TypeScript (seperti penggunaan enum tertentu atau sintaks dekorator yang lebih lama jika dikonfigurasi) menjadi JavaScript yang setara.
  3. Menangani JSX: Mengubah sintaks JSX (digunakan dalam file .tsx dan .jsx) menjadi panggilan fungsi JavaScript standar (biasanya React.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 selama run), 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 handler fetch standar. (Dibahas secara rinci nanti).
  • Bun.file(path): Membuat objek BunFile, 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 ekuivalen node:fs.
  • Bun.write(path, data): Pasangan dari Bun.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 dengan child_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 dengan process.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:

  1. 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.
  2. Keterbiasaan: Pengembang yang sudah familiar dengan API browser dapat memanfaatkan pengetahuan tersebut saat bekerja dengan Bun, mengurangi kurva pembelajaran.
  3. 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.
  4. 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 menjadi Uint8Array (biasanya UTF-8).
  • TextDecoder: Mendekode Uint8Array menjadi string.

Blob API:

  • Blob: Merepresentasikan data mentah yang tidak dapat diubah, sering digunakan untuk objek seperti file.
  • File: Memperluas Blob untuk merepresentasikan file, termasuk metadata seperti nama dan tanggal modifikasi terakhir. (Sering dibuat melalui Bun.file().slice() atau dari data form).

FormData API:

  • FormData: Untuk membangun kumpulan pasangan kunci/nilai, sering digunakan untuk mengirimkan data form dalam permintaan fetch.

WebSocket API:

  • WebSocket: API sisi klien untuk membangun koneksi WebSocket. (Penanganan sisi server terintegrasi ke dalam Bun.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 objek Request dan Response standar.
  • Objek Permintaan: Parameter req menyediakan akses ke properti dan metode Request standar: req.url, req.method, req.headers, req.json(), req.text(), req.arrayBuffer(), req.formData(), req.body (sebuah ReadableStream).
  • 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 luar try...catch handler fetch. Kesalahan dalam handler fetch asynchronous biasanya harus ditangkap di sana.
  • Streaming: Body permintaan dan respons dapat di-stream menggunakan API ReadableStream dan WritableStream standar, penting untuk menangani unggahan atau unduhan besar secara efisien.
  • Pemuatan Ulang Dinamis: Metode server.reload() memungkinkan pembaruan opsi server, termasuk handler fetch dan error, 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 dengan Content-Type yang sesuai.
  • ReadableStream: Mengalirkan konten body, cocok untuk unggahan besar.
  • URLSearchParams: Secara otomatis mengatur Content-Type ke application/x-www-form-urlencoded.
  • FormData: Secara otomatis mengatur Content-Type ke multipart/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: Objek Headers untuk mengakses header respons.
  • Metode Pembacaan Body: response.json(), response.text(), response.arrayBuffer(), response.blob(), response.formData(). Ini mengembalikan Promise.
  • response.body: Sebuah ReadableStream 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 handler fetch, mencoba menyelesaikan handshake WebSocket. Jika berhasil, ia mengembalikan true, dan Bun mengambil alih koneksi menggunakan handler websocket. Jika gagal, ia mengembalikan false. Anda harus mengembalikan undefined dari fetch setelah upgrade berhasil.
  • Objek Handler websocket: Berisi fungsi open, message, close, dan drain untuk mengelola siklus hidup WebSocket untuk klien yang terhubung.
  • ServerWebSocket<T>: Tipe yang merepresentasikan koneksi WebSocket sisi server. Generik T mendefinisikan tipe objek ws.data.
  • ws.data: Objek yang terkait dengan setiap koneksi, diinisialisasi oleh properti data dalam opsi server.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 pengirim ws.
  • 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 alat Pengujian API hebat yang menghasilkan Dokumentasi API yang indah?

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!
button