DEV Community

Cover image for Bun overview
Željko Šević
Željko Šević

Posted on • Originally published at sevic.dev on

Bun overview

Bun is a JavaScript runtime built on JavaScriptCore (the engine behind Safari). It is designed for speed and developer experience (DX), bundling many tools into a single binary.

Some of the features include

  • Built-in bundler
  • Built-in test runner
  • Node.js-compatible package manager, compatible with existing npm packages
  • Compatibility with Node.js native modules like fs, path, etc.
  • TypeScript support, run TypeScript files with no extra configuration
  • Built-in watch mode and hot reloading
  • Support for both ES modules and CommonJS modules, both can be used in the same file
  • Native SQLite driver
  • Built-in PostgreSQL, MySQL, and Redis clients

Installation

Install on macOS and Linux:

curl -fsSL https://bun.com/install | bash
Enter fullscreen mode Exit fullscreen mode

Install on Windows (PowerShell):

powershell -c "irm bun.com/install.ps1|iex"
Enter fullscreen mode Exit fullscreen mode

Other options include npm install -g bun, Homebrew, Scoop, and Docker. See the installation docs for details.

Update the current version with the bun upgrade command and check the current version with bun --version.

Run bun --help to see what CLI options are available.

Initialize an empty project via the bun init command.

The init command bootstraps a "hello world" example with package.json, a text lock file (bun.lock), and tsconfig.json.

Bundler

The bundler can be used via the CLI (bun build) or the Bun.build() API.

await Bun.build({
  entrypoints: ['./index.ts'],
  outdir: './build'
});
Enter fullscreen mode Exit fullscreen mode

Below is an example for CLI usage. Run bun build --help to see all available options.

bun build --target=bun ./index.ts --outdir=./build
Enter fullscreen mode Exit fullscreen mode

Build a single executable using the --compile flag.

bun build ./index.ts --compile --outfile myapp
Enter fullscreen mode Exit fullscreen mode

Bun can also bundle full-stack apps by importing HTML from server code and embed frontend assets into a standalone binary.

Package manager

Install packages from package.json via the bun install command.

Install additional npm packages via the bun add command (e.g., bun add zod). To install dev dependencies, run bun add with the --dev option (e.g., bun add zod --dev).

Remove dependencies via the bun remove command (e.g., bun remove zod).

Running scripts

  • Run a specific script via the bun <SCRIPT PATH>.ts command
  • Auto-install and run packages locally via the bunx command (e.g., bunx cowsay "Hello world")
  • Run a custom npm script from package.json via the bun run <SCRIPT NAME> command

Watch mode

  • Hot reloading via bun --hot index.ts without restarting the process
  • Watch mode via bun --watch index.ts with restarting the process

File system

Write into a file using the Bun.write method.

await Bun.write('./output.txt', 'Lorem ipsum');
Enter fullscreen mode Exit fullscreen mode

Environment variables

  • Access environment variables via Bun.env, process.env, or import.meta.env
  • Store variables in .env files, like .env, .env.production, .env.local
  • Print all current environment variables (including values loaded from .env) via bun --print process.env

HTTP server

Create a server with the following code.

const port = Number(Bun.env.PORT) || 3000;

const server = Bun.serve({
  port,
  fetch() {
    return new Response('Welcome to Bun!');
  }
});

console.log(`Listening on port ${server.port}`);
Enter fullscreen mode Exit fullscreen mode

Frameworks

Elysia (Bun framework)

Install packages via bun add elysia @elysiajs/openapi, write the initial server, and run it via bun server.ts.

// server.ts
import { Elysia } from 'elysia';
import { openapi } from '@elysiajs/openapi';

const port = Number(Bun.env.PORT) || 8081;

new Elysia()
  .use(openapi())
  .get('/posts/:id', ({ params: { id } }) => id)
  .listen(port);
Enter fullscreen mode Exit fullscreen mode

OpenAPI docs are served at /openapi by default.

Express

Install the express package via bun add express, write the initial server, and run it via bun server.ts.

// server.ts
import express from 'express';

const app = express();
const port = Number(Bun.env.PORT) || 3001;

app.get('/', (req, res) => {
  res.send('Hello world');
});

app.listen(port, () => {
  console.log(`Listening on port ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Debugging

Install the extension Bun for Visual Studio Code by Oven and run the Bun: Debug file command from the command palette. Execution will pause at the breakpoint.

Testing

Bun supports basic mocking and assertion functions. Run existing tests via bun run <TEST SCRIPT NAME> (e.g., bun run test:unit).

Below is an example of a basic test assertion and mocking using the bun:test module.

import { describe, expect, it, mock } from 'bun:test';
import { add } from './addition-service';
import { calculate } from './calculation-service';

describe('Calculation service', () => {
  it('should return calculated value', async () => {
    const result = calculate();

    expect(result).toEqual(5);
  });

  it('should return mocked value', async () => {
    mock.module('./addition-service', () => {
      return {
        add: () => 3
      };
    });

    const result = add();

    expect(result).toEqual(3);
  });
});
Enter fullscreen mode Exit fullscreen mode

Run unit tests via the bun test command. Re-run tests when files change via bun test --watch.

SQLite database

Below is a basic example of SQLite driver usage.

import { Database } from 'bun:sqlite';

const database = new Database('database.sqlite');
const query = database.query("SELECT 'hello world' as message;");
console.log(query.get());
database.close();
Enter fullscreen mode Exit fullscreen mode

Demo

Runnable Bun scripts for this post live in the bun-overview-demo folder. Get access via code demos.

Top comments (0)