Bun overview
September 11, 2023Bun is a JavaScript runtime environment that extends JavaScriptCore engine built for Safari. Bun is designed for speed and developer experience (DX), which includes many features out of the box.
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
- Support for both ES modules and CommonJS modules, both can be used in the same file
- Native SQLite driver
Installation
Let's start by installing it with the following command
curl -fsSL https://bun.sh/install | bash
Update the current version with bun upgrade command and check the current version with bun --version command.
Run bun --help to see what CLI options are available.
Initialize empty project via the bun init command
The init command will bootstrap the "hello world" example with configured package.json, binary lock file (bun.lockb), and tsconfig.
Bundler
Bundler can be used via CLI command (bun build) or Bun.build() API
await Bun.build({entrypoints: ['./index.ts'],outdir: './build'});
Below is the example for CLI command usage. Run bun build --help to see all of the available options
bun build --target=bun ./index.ts --outdir=./build
Build a single executable using the compile flag.
bun build ./index.js --compile
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 --dev option (e.g., bun add zod --dev)
Remove dependencies via the bun remove command (e.g., bun remove zod)
Running scripts
- Run specific script via the
bun <SCRIPT PATH>.tscommand - Auto-install and run packages locally via the
bunxcommand (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 mode via
bun --hot index.tscommand without restarting the process - watch mode via
bun --watch index.tscommand with restarting the process
File system
Write into the file using Bun.write method
await Bun.write('./output.txt', 'Lorem ipsum');
Environment variables
- Access environment variables via
Bun.envorprocess.envobjects - Store variables in
.envfiles, like.env,.env.production,.env.local - Print all current environment variables via
bun run envcommand
HTTP server
Create a server with the following code
const server = Bun.serve({port: Bun.env.PORT,fetch(request) {return new Response('Welcome to Bun!');}});console.log(`Listening to port ${server.port}`);
Frameworks
Elysia (Bun framework)
Install packages via the bun add elysia @elysiajs/swagger command, write the initial server, and run it via the bun server.ts command.
// server.tsimport { Elysia } from 'elysia';import swagger from '@elysiajs/swagger';const port = Bun.env.PORT || 8081;new Elysia().use(swagger({path: '/api-docs'})).get('/posts/:id', ({ params: { id } }) => id).listen(port);
Express
Install the express package via the bun add express command, write the initial server, and run it via the bun server.ts command
// server.tsimport express from 'express';const app = express();const port = Bun.env.PORT || 3001;app.get('/', (req, res) => {res.send('Hello world');});app.listen(port, () => {console.log(`Listening on port ${port}`);});
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 the bun run <TEST SCRIPT NAME> (e.g., bun run test:unit) command.
Below is an example of a basic test assertion and mocking using 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);});});
Run unit tests via the bun test command. Re-run tests when files change via the bun test --watch command.
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();