Bun is a fast all-in-one JavaScript runtime and toolkit designed as a drop-in replacement for Node.js. It implements a native bundler, transpiler, task runner, and npm-compatible package manager - all in a single executable.
Bun focuses on three main design goals: Speed (Bun starts fast and runs fast), Elegant APIs (minimal set of highly-optimized APIs), and Cohesive Developer Experience (complete toolkit for building JavaScript apps).
In the following tutorial I’m going to demonstrate how to use Bun for common development tasks like package management, running TypeScript, bundling, and testing.
Installation
Installing Bun is straightforward. On macOS, Linux, and WSL, run:
curl -fsSL https://bun.sh/install | bash
My preferred way is using mise (feel free to read my article about mise here):
mise install bun
After installation, verify it’s working:
bun --version
Running JavaScript and TypeScript Files
Bun can execute JavaScript and TypeScript files directly without any configuration.
Running a Simple Script
Create a simple JavaScript file:
console.log("Hello from Bun!");
const performance_start = performance.now();
const result = await fetch("https://api.github.com/users/github");
const data = await result.json();
const performance_end = performance.now();
console.log(`Fetched GitHub data in ${(performance_end - performance_start).toFixed(2)}ms`);
console.log(`GitHub joined: ${data.created_at}`);
Run the script with Bun:
bun run hello.js
Output
Running the code above should produce a similar output:
Hello from Bun!
Fetched GitHub data in 245.32ms
GitHub joined: 2008-01-25T15:55:12Z
Running TypeScript
Bun supports TypeScript out of the box without any configuration:
interface User {
name: string;
email: string;
role: "admin" | "user";
}
const greetUser = (user: User): string => {
return `Welcome ${user.name}! You are logged in as ${user.role}.`;
};
const currentUser: User = {
name: "Alice",
email: "alice@example.com",
role: "admin"
};
console.log(greetUser(currentUser));
Run the TypeScript file directly:
bun run hello.ts
Output
Welcome Alice! You are logged in as admin.
Package Management
Bun includes a fast npm-compatible package manager that can install packages significantly faster than npm or yarn.
Creating a New Project
Initialize a new project:
bun init
This creates a new project with a package.json and basic TypeScript configuration.
Installing Dependencies
Install packages using Bun’s package manager:
bun add express
bun add -d @types/express
Example using Express:
import express from "express";
const app = express();
const port = 3000;
app.get("/", (req, res) => {
res.json({
message: "Hello from Bun + Express, visit www.hascode.com! :D!",
timestamp: new Date().toISOString()
});
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
Run the server:
bun run server.ts
Output
Server running at http://localhost:3000
Built-in HTTP Server
Bun includes a fast built-in HTTP server with Web standard Request and Response objects.
Creating a Simple HTTP Server
const server = Bun.serve({
port: 3000,
fetch(request) {
const url = new URL(request.url);
if (url.pathname === "/") {
return new Response("Welcome to Bun!");
}
if (url.pathname === "/api/time") {
return Response.json({
time: new Date().toISOString(),
timestamp: Date.now()
});
}
return new Response("Not Found", { status: 404 });
},
});
console.log(`Server listening on http://localhost:${server.port}`);
Run the server:
bun run bun-server.ts
Output
Server listening on http://localhost:3000
Test the endpoints:
curl http://localhost:3000/
curl http://localhost:3000/api/time
File System Operations
Bun provides optimized file system APIs that are faster than Node.js equivalents.
Reading and Writing Files
// Writing a file
await Bun.write("output.txt", "Hello from Bun!");
console.log("File written successfully");
// Reading a file as text
const text = await Bun.file("output.txt").text();
console.log(`Read text: ${text}`);
// Reading as JSON
const jsonData = { name: "Bun", version: "1.0", fast: true };
await Bun.write("data.json", JSON.stringify(jsonData, null, 2));
const data = await Bun.file("data.json").json();
console.log(`Parsed JSON: ${data.name} v${data.version}`);
// File exists check
const exists = await Bun.file("output.txt").exists();
console.log(`File exists: ${exists}`);
Run the file operations:
bun run file-operations.ts
Output
File written successfully
Read text: Hello from Bun!
Parsed JSON: Bun v1.0
File exists: true
Bundling
Bun includes a fast JavaScript bundler that can bundle your code for production.
Creating a Bundle
import { greet } from "./utils";
console.log(greet("World, visit www.hascode.com!"));
export const greet = (name: string): string => {
return `Hello, ${name}!`;
};
Bundle the application:
bun build ./app.ts --outdir ./dist --target browser
This creates an optimized bundle in the dist directory.
For minification:
bun build ./app.ts --outdir ./dist --minify
We can now run our app like this:
bun run app.ts
Hello, World, visit www.hascode.com!!
Testing
Bun includes a fast built-in test runner compatible with Jest APIs.
Writing Tests
export const add = (a: number, b: number): number => a + b;
export const multiply = (a: number, b: number): number => a * b;
import { test, expect, describe } from "bun:test";
import { add, multiply } from "./math";
describe("Math operations", () => {
test("add two numbers", () => {
expect(add(2, 3)).toBe(5);
expect(add(-1, 1)).toBe(0);
});
test("multiply two numbers", () => {
expect(multiply(3, 4)).toBe(12);
expect(multiply(0, 5)).toBe(0);
});
});
Run the tests:
bun test
Output
bun test
bun test v1.4.2 (744846f84)
math.test.ts:
✓ Math operations > add two numbers [0.03ms]
✓ Math operations > multiply two numbers [0.03ms]
2 pass
0 fail
4 expect() calls
Ran 2 tests across 1 file. [3.00ms]
Environment Variables
Bun automatically loads environment variables from .env files.
Using Environment Variables
DATABASE_URL=postgresql://localhost:5432/mydb
API_KEY=secret_key_123
console.log(`Database URL: ${process.env.DATABASE_URL}`);
console.log(`API Key: ${process.env.API_KEY}`);
// Bun also provides Bun.env
console.log(`Using Bun.env: ${Bun.env.DATABASE_URL}`);
Run the script:
bun run config.ts
Output
Database URL: postgresql://localhost:5432/mydb
API Key: secret_key_123
Using Bun.env: postgresql://localhost:5432/mydb
WebSocket Server
Bun provides built-in WebSocket support with excellent performance.
Creating a WebSocket Server
const server = Bun.serve({
port: 3000,
fetch(req, server) {
const success = server.upgrade(req);
if (success) {
return undefined;
}
return new Response("Upgrade failed", { status: 500 });
},
websocket: {
message(ws, message) {
console.log(`Received: ${message}`);
ws.send(`Echo: ${message}`);
},
open(ws) {
console.log("Client connected");
ws.send("Welcome to Bun WebSocket!");
},
close(ws) {
console.log("Client disconnected");
},
},
});
console.log(`WebSocket server running on ws://localhost:${server.port}`);
Run the WebSocket server:
bun run websocket-server.ts
Output
WebSocket server running on ws://localhost:3000