| name | bun |
| description | Configures Bun as an all-in-one JavaScript runtime, bundler, package manager, and test runner with native TypeScript support. Use when building fast applications, bundling for production, or replacing Node.js tooling. |
Bun
All-in-one JavaScript runtime, bundler, package manager, and test runner written in Zig.
Quick Start
# Install Bun
curl -fsSL https://bun.sh/install | bash
# Or with npm
npm install -g bun
# Run TypeScript directly
bun run src/index.ts
# Install packages
bun install
# Bundle for production
bun build src/index.ts --outdir=dist
Runtime
Running Files
# Run TypeScript/JavaScript
bun run index.ts
bun run index.js
bun run index.jsx
bun run index.tsx
# Run package.json scripts
bun run dev
bun run build
# Shorthand for run
bun dev
bun build
Watch Mode
# Auto-restart on changes
bun --watch run index.ts
# Hot reload (preserves state)
bun --hot run index.ts
Environment Variables
# Load .env automatically
bun run index.ts
# Specify env file
bun --env-file=.env.local run index.ts
# No env file
bun --no-env-file run index.ts
Package Manager
Install Packages
# Install all dependencies
bun install
# Add package
bun add express
bun add -D typescript
# Add exact version
bun add react@18.2.0
# Global install
bun add -g typescript
Remove/Update
# Remove package
bun remove lodash
# Update packages
bun update
bun update react
Lock File
# Generate/update bun.lockb
bun install
# Frozen install (CI)
bun install --frozen-lockfile
# Convert to yarn.lock
bun pm pack
Bundler
Basic Bundling
# Bundle for browser
bun build src/index.ts --outdir=dist
# Single file output
bun build src/index.ts --outfile=dist/bundle.js
# Minify
bun build src/index.ts --outdir=dist --minify
# Source maps
bun build src/index.ts --outdir=dist --sourcemap=external
Build API
// build.ts
const result = await Bun.build({
entrypoints: ['./src/index.tsx'],
outdir: './dist',
minify: true,
sourcemap: 'external',
target: 'browser',
splitting: true,
format: 'esm',
});
if (!result.success) {
console.error('Build failed:', result.logs);
process.exit(1);
}
console.log('Build complete!', result.outputs);
Bundle Options
await Bun.build({
entrypoints: ['./src/index.ts', './src/worker.ts'],
outdir: './dist',
// Target
target: 'browser', // 'browser' | 'bun' | 'node'
// Format
format: 'esm', // 'esm' | 'cjs' | 'iife'
// Optimization
minify: {
whitespace: true,
identifiers: true,
syntax: true,
},
sourcemap: 'external', // 'none' | 'inline' | 'external' | 'linked'
// Code splitting
splitting: true,
// Naming
naming: {
entry: '[dir]/[name].[ext]',
chunk: 'chunks/[name]-[hash].[ext]',
asset: 'assets/[name]-[hash].[ext]',
},
// Externals
external: ['react', 'react-dom'],
// Define
define: {
'process.env.NODE_ENV': JSON.stringify('production'),
},
// Loaders
loader: {
'.png': 'file',
'.svg': 'dataurl',
},
// Public path
publicPath: '/assets/',
// Plugins
plugins: [],
});
Plugins
const myPlugin = {
name: 'my-plugin',
setup(build) {
// Resolve hook
build.onResolve({ filter: /^env$/ }, (args) => {
return { path: args.path, namespace: 'env-ns' };
});
// Load hook
build.onLoad({ filter: /.*/, namespace: 'env-ns' }, () => {
return {
contents: `export const API = "${process.env.API_URL}"`,
loader: 'js',
};
});
},
};
await Bun.build({
entrypoints: ['./src/index.ts'],
plugins: [myPlugin],
});
Test Runner
Running Tests
# Run all tests
bun test
# Specific file
bun test src/utils.test.ts
# Pattern matching
bun test --test-name-pattern "should handle"
# Watch mode
bun test --watch
# Coverage
bun test --coverage
Writing Tests
// math.test.ts
import { describe, test, expect, beforeEach, mock } from 'bun:test';
describe('math', () => {
test('adds numbers', () => {
expect(1 + 2).toBe(3);
});
test('async operations', async () => {
const result = await fetchData();
expect(result).toBeDefined();
});
});
// Mocking
const mockFn = mock(() => 42);
mockFn();
expect(mockFn).toHaveBeenCalled();
// Spying
import * as module from './module';
const spy = spyOn(module, 'someFunction');
Test Configuration
// bunfig.toml
[test]
root = "./tests"
timeout = 5000
preload = ["./setup.ts"]
coverage = true
coverageReporter = ["text", "lcov"]
HTTP Server
Bun.serve
const server = Bun.serve({
port: 3000,
hostname: '0.0.0.0',
fetch(req) {
const url = new URL(req.url);
if (url.pathname === '/') {
return new Response('Hello World!');
}
if (url.pathname === '/api/data') {
return Response.json({ message: 'Hello' });
}
return new Response('Not Found', { status: 404 });
},
// WebSocket support
websocket: {
message(ws, message) {
ws.send(`Echo: ${message}`);
},
open(ws) {
console.log('Client connected');
},
close(ws) {
console.log('Client disconnected');
},
},
});
console.log(`Server running at http://localhost:${server.port}`);
Static Files
Bun.serve({
port: 3000,
async fetch(req) {
const url = new URL(req.url);
const filePath = `./public${url.pathname}`;
const file = Bun.file(filePath);
if (await file.exists()) {
return new Response(file);
}
return new Response('Not Found', { status: 404 });
},
});
File System
Reading Files
// Read text
const text = await Bun.file('file.txt').text();
// Read JSON
const json = await Bun.file('data.json').json();
// Read ArrayBuffer
const buffer = await Bun.file('image.png').arrayBuffer();
// Check existence
const exists = await Bun.file('file.txt').exists();
// Get file info
const file = Bun.file('file.txt');
console.log(file.size, file.type);
Writing Files
// Write text
await Bun.write('output.txt', 'Hello World');
// Write JSON
await Bun.write('data.json', JSON.stringify(data, null, 2));
// Write Buffer
await Bun.write('output.bin', buffer);
// Append
const file = Bun.file('log.txt');
await Bun.write(file, await file.text() + '\nNew line');
Shell Commands
import { $ } from 'bun';
// Simple command
await $`echo "Hello World"`;
// With variables
const name = 'World';
await $`echo "Hello ${name}"`;
// Capture output
const result = await $`ls -la`.text();
// Check exit code
const { exitCode } = await $`npm test`.nothrow();
// Pipe commands
await $`cat file.txt | grep "pattern"`;
// Environment variables
await $`API_KEY=${key} node script.js`;
Standalone Executables
# Compile to single executable
bun build --compile src/cli.ts --outfile my-cli
# Cross-compile
bun build --compile --target=bun-linux-x64 src/cli.ts
bun build --compile --target=bun-darwin-arm64 src/cli.ts
bun build --compile --target=bun-windows-x64 src/cli.ts
Configuration
bunfig.toml
# Package manager
[install]
registry = "https://registry.npmjs.org"
scope = { "@company" = "https://private.registry.com" }
# Bundler
[bundle]
entrypoints = ["./src/index.ts"]
outdir = "./dist"
minify = true
sourcemap = "external"
# Test runner
[test]
root = "./tests"
preload = ["./setup.ts"]
timeout = 5000
# Development server
[serve]
port = 3000
See references/api.md for complete API reference and references/migration.md for Node.js migration guide.