Bun: The Fast JavaScript Runtime and Toolkit
Master Bun for JavaScript development. Learn the runtime, package manager, bundler, test runner, and build faster applications with Bun.
Moshiour Rahman
Advertisement
What is Bun?
Bun is a fast all-in-one JavaScript runtime, bundler, transpiler, and package manager. Built from scratch in Zig, it’s designed to be a drop-in replacement for Node.js with dramatically better performance.
Bun vs Node.js
| Feature | Bun | Node.js |
|---|---|---|
| Speed | 4x faster | Baseline |
| TypeScript | Native | Requires setup |
| JSX | Native | Requires setup |
| Package Manager | Built-in | npm/yarn |
| Bundler | Built-in | External |
| Test Runner | Built-in | External |
Getting Started
Installation
# macOS/Linux
curl -fsSL https://bun.sh/install | bash
# Windows (via WSL)
curl -fsSL https://bun.sh/install | bash
# Homebrew
brew install oven-sh/bun/bun
# npm
npm install -g bun
Create Project
# Create new project
bun init
# Create from template
bun create react my-app
bun create next my-app
bun create svelte my-app
Running JavaScript/TypeScript
Execute Files
# Run JavaScript
bun run index.js
# Run TypeScript (no config needed)
bun run index.ts
# Run with watch mode
bun --watch run index.ts
# Run script from package.json
bun run dev
bun dev # shorthand
TypeScript Support
// index.ts - No configuration needed!
interface User {
id: number;
name: string;
email: string;
}
const users: User[] = [
{ id: 1, name: 'John', email: 'john@example.com' }
];
console.log(users);
// JSX works too
const element = <div>Hello World</div>;
Package Manager
Install Dependencies
# Install all dependencies
bun install
# Add package
bun add express
bun add -d typescript # dev dependency
# Add specific version
bun add react@18.2.0
# Remove package
bun remove express
# Update packages
bun update
bun update react
# Global install
bun add -g typescript
Workspace Support
// package.json
{
"workspaces": [
"packages/*"
]
}
# Install workspace dependencies
bun install
# Run command in workspace
bun --filter my-package run build
HTTP Server
Basic Server
// server.ts
const server = Bun.serve({
port: 3000,
fetch(req) {
const url = new URL(req.url);
if (url.pathname === '/') {
return new Response('Hello World!');
}
if (url.pathname === '/json') {
return Response.json({ message: 'Hello JSON' });
}
return new Response('Not Found', { status: 404 });
}
});
console.log(`Server running at http://localhost:${server.port}`);
Routing
const server = Bun.serve({
port: 3000,
async fetch(req) {
const url = new URL(req.url);
const method = req.method;
// GET /api/users
if (method === 'GET' && url.pathname === '/api/users') {
const users = await getUsers();
return Response.json(users);
}
// POST /api/users
if (method === 'POST' && url.pathname === '/api/users') {
const body = await req.json();
const user = await createUser(body);
return Response.json(user, { status: 201 });
}
// GET /api/users/:id
const userMatch = url.pathname.match(/^\/api\/users\/(\d+)$/);
if (method === 'GET' && userMatch) {
const user = await getUser(userMatch[1]);
if (!user) {
return Response.json({ error: 'Not found' }, { status: 404 });
}
return Response.json(user);
}
return new Response('Not Found', { status: 404 });
}
});
WebSocket Server
const server = Bun.serve({
port: 3000,
fetch(req, server) {
// Upgrade to WebSocket
if (server.upgrade(req)) {
return;
}
return new Response('Expected WebSocket', { status: 400 });
},
websocket: {
open(ws) {
console.log('Client connected');
ws.subscribe('chat');
},
message(ws, message) {
console.log('Received:', message);
// Broadcast to all subscribers
ws.publish('chat', message);
},
close(ws) {
console.log('Client disconnected');
ws.unsubscribe('chat');
}
}
});
File I/O
Reading Files
// Read as text
const text = await Bun.file('file.txt').text();
// Read as JSON
const config = await Bun.file('config.json').json();
// Read as ArrayBuffer
const buffer = await Bun.file('image.png').arrayBuffer();
// Read as stream
const file = Bun.file('large-file.txt');
const stream = file.stream();
// Check if file exists
const exists = await Bun.file('file.txt').exists();
// Get file info
const file = Bun.file('file.txt');
console.log(file.size); // bytes
console.log(file.type); // MIME type
Writing Files
// Write text
await Bun.write('output.txt', 'Hello World');
// Write JSON
await Bun.write('data.json', JSON.stringify({ name: 'John' }));
// Write from Response
const response = await fetch('https://example.com/file');
await Bun.write('downloaded.html', response);
// Append to file
const file = Bun.file('log.txt');
const writer = file.writer();
writer.write('Log entry 1\n');
writer.write('Log entry 2\n');
await writer.end();
SQLite Database
import { Database } from 'bun:sqlite';
// Create/open database
const db = new Database('mydb.sqlite');
// Create table
db.run(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
)
`);
// Insert data
const insert = db.prepare(
'INSERT INTO users (name, email) VALUES (?, ?)'
);
insert.run('John', 'john@example.com');
// Query data
const query = db.prepare('SELECT * FROM users WHERE id = ?');
const user = query.get(1);
console.log(user);
// Query all
const allUsers = db.prepare('SELECT * FROM users').all();
console.log(allUsers);
// Transaction
const insertMany = db.transaction((users) => {
const insert = db.prepare(
'INSERT INTO users (name, email) VALUES (?, ?)'
);
for (const user of users) {
insert.run(user.name, user.email);
}
});
insertMany([
{ name: 'Alice', email: 'alice@example.com' },
{ name: 'Bob', email: 'bob@example.com' }
]);
Bundler
Bundle for Browser
# Bundle JavaScript
bun build ./src/index.ts --outdir ./dist
# With minification
bun build ./src/index.ts --outdir ./dist --minify
# Multiple entry points
bun build ./src/index.ts ./src/worker.ts --outdir ./dist
# External dependencies
bun build ./src/index.ts --outdir ./dist --external react
Build Configuration
// build.ts
await Bun.build({
entrypoints: ['./src/index.tsx'],
outdir: './dist',
minify: true,
splitting: true,
sourcemap: 'external',
target: 'browser',
define: {
'process.env.NODE_ENV': JSON.stringify('production')
},
external: ['react', 'react-dom']
});
Test Runner
Writing Tests
// math.test.ts
import { describe, it, expect, beforeAll, afterAll } from 'bun:test';
describe('Math operations', () => {
it('should add numbers', () => {
expect(1 + 1).toBe(2);
});
it('should multiply numbers', () => {
expect(2 * 3).toBe(6);
});
});
describe('Async tests', () => {
it('should handle async operations', async () => {
const result = await Promise.resolve(42);
expect(result).toBe(42);
});
});
describe('Matchers', () => {
it('toBe', () => {
expect(1).toBe(1);
});
it('toEqual', () => {
expect({ a: 1 }).toEqual({ a: 1 });
});
it('toContain', () => {
expect([1, 2, 3]).toContain(2);
});
it('toThrow', () => {
expect(() => {
throw new Error('fail');
}).toThrow('fail');
});
it('toBeGreaterThan', () => {
expect(10).toBeGreaterThan(5);
});
});
Run Tests
# Run all tests
bun test
# Run specific file
bun test math.test.ts
# Watch mode
bun test --watch
# With coverage
bun test --coverage
Mocking
import { mock, spyOn } from 'bun:test';
// Mock function
const mockFn = mock(() => 42);
mockFn();
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(1);
// Spy on object method
const obj = {
method: () => 'original'
};
const spy = spyOn(obj, 'method').mockReturnValue('mocked');
expect(obj.method()).toBe('mocked');
expect(spy).toHaveBeenCalled();
Environment Variables
// Access environment variables
const apiKey = Bun.env.API_KEY;
const port = Bun.env.PORT || 3000;
// .env files are loaded automatically
// .env
// API_KEY=secret123
// PORT=8080
// Access with process.env (Node.js compatibility)
console.log(process.env.API_KEY);
Shell Commands
import { $ } from 'bun';
// Run shell commands
const result = await $`ls -la`;
console.log(result.text());
// With variables
const dir = './src';
await $`ls ${dir}`;
// Check exit code
const { exitCode } = await $`npm test`;
if (exitCode !== 0) {
console.log('Tests failed');
}
// Pipe commands
await $`cat file.txt | grep "pattern"`;
// Capture output
const output = await $`echo "Hello"`.text();
console.log(output); // "Hello\n"
Node.js Compatibility
// Most Node.js APIs work
import fs from 'fs';
import path from 'path';
import { createServer } from 'http';
// Read file (Node.js style)
const content = fs.readFileSync('file.txt', 'utf-8');
// Create HTTP server (Node.js style)
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
});
server.listen(3000);
Hono Framework
// Perfect combination with Hono
import { Hono } from 'hono';
const app = new Hono();
app.get('/', (c) => c.text('Hello Hono!'));
app.get('/api/users', async (c) => {
const users = await getUsers();
return c.json(users);
});
app.post('/api/users', async (c) => {
const body = await c.req.json();
const user = await createUser(body);
return c.json(user, 201);
});
export default app;
// Or with Bun.serve
export default {
port: 3000,
fetch: app.fetch
};
Summary
| Feature | Command |
|---|---|
| Run | bun run file.ts |
| Install | bun install |
| Add Package | bun add package |
| Build | bun build |
| Test | bun test |
| Start Server | bun run server.ts |
Bun provides a fast, all-in-one toolkit for modern JavaScript and TypeScript development.
Advertisement
Moshiour Rahman
Software Architect & AI Engineer
Enterprise software architect with deep expertise in financial systems, distributed architecture, and AI-powered applications. Building large-scale systems at Fortune 500 companies. Specializing in LLM orchestration, multi-agent systems, and cloud-native solutions. I share battle-tested patterns from real enterprise projects.
Related Articles
Deno 2.0: The Modern JavaScript Runtime That's Ready for Production
Master Deno 2.0 for modern JavaScript and TypeScript development. Learn built-in tooling, npm compatibility, security model, and migration from Node.js.
JavaScriptTypeScript Advanced Guide: Types, Generics, and Patterns
Master advanced TypeScript concepts. Learn generics, utility types, conditional types, mapped types, and professional patterns for type-safe code.
JavaScriptGraphQL API Development: Complete Guide with Node.js
Master GraphQL API development from scratch. Learn schema design, resolvers, queries, mutations, subscriptions, and authentication best practices.
Comments
Comments are powered by GitHub Discussions.
Configure Giscus at giscus.app to enable comments.