notes/converting-to-bun

Converting from npm to Bun

January 13, 2025·3 min read

Complete guide to converting an npm-based project to Bun, including Docker, CI/CD, and deployment configurations.

Why Bun?

  • 10-100x faster package installation than npm
  • Drop-in replacement for Node.js - no code changes needed
  • Built-in bundler and test runner
  • Smaller Docker images when using Bun base image

Prerequisites

  • Existing project using npm
  • Admin/sudo access (for Bun installation)

Step 1: Install Bun

Windows (PowerShell)

irm bun.sh/install.ps1 | iex

macOS/Linux

curl -fsSL https://bun.sh/install | bash

Verify installation:

bun --version

Step 2: Install Dependencies with Bun

In your project directory:

# Remove npm lock file (optional but recommended)
rm package-lock.json

# Install dependencies with Bun
bun install

This creates a bun.lock file (Bun's lockfile) and installs all packages from package.json.

Note: package.json stays the same - no changes needed!

Step 3: Test Your Build

Verify everything works:

bun run build
bun run dev
bun run test

All npm scripts work as-is with bun run.

Step 4: Update Dockerfile

If you use Docker, update your Dockerfile to use Bun:

Before (npm):

FROM node:20-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

After (Bun):

FROM oven/bun:1 AS builder
WORKDIR /app
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build

Key changes:

  • Base image: oven/bun:1
  • Copy bun.lock instead of package-lock.json
  • Use bun install --frozen-lockfile (like npm ci)

Step 5: Update CI/CD Pipeline

GitHub Actions

Before:

- name: Set up Node.js
  uses: actions/setup-node@v4
  with:
    node-version: '20'

- name: Install dependencies
  run: npm install

- name: Build
  run: npm run build

After:

- name: Set up Bun
  uses: oven-sh/setup-bun@v2
  with:
    bun-version: latest

- name: Install dependencies
  run: bun install --frozen-lockfile

- name: Build
  run: bun run build

Cloudflare Workers/Pages

No changes needed! Wrangler works with Bun out of the box.

Just update your npm scripts:

{
  "scripts": {
    "deploy": "bun run build && wrangler pages deploy public"
  }
}

Step 6: Update .gitignore

Add Bun-specific ignores:

# Dependencies
node_modules/

# Lock files (choose one approach)
# Option 1: Keep both for compatibility
package-lock.json
yarn.lock

# Option 2: Bun only (remove npm lock from git)
# package-lock.json committed previously will be ignored

Note: bun.lock should be committed to git (just like package-lock.json).

Common Commands

npm Bun Description
npm install bun install Install dependencies
npm install <pkg> bun add <pkg> Add package
npm install -D <pkg> bun add -d <pkg> Add dev dependency
npm uninstall <pkg> bun remove <pkg> Remove package
npm run <script> bun run <script> Run package.json script
npx <command> bunx <command> Execute package binary
npm ci bun install --frozen-lockfile Clean install

Verification Checklist

After conversion, verify:

  • bun install completes successfully
  • bun run build works
  • bun run dev starts dev server
  • All tests pass with bun run test
  • Docker build succeeds (if applicable)
  • CI/CD pipeline passes
  • Production deployment works

Troubleshooting

Peer Dependency Warnings

Bun may show peer dependency warnings. These are usually safe to ignore:

warn: incorrect peer dependency "[email protected]"

Native Modules

Most native modules work. If you encounter issues:

bun install --force

Postinstall Scripts

Some packages have postinstall scripts. Check with:

bun pm untrusted

Run blocked postinstall scripts:

bun pm trust <package-name>

Performance Comparison

Real-world example (this blog):

Operation npm Bun Speedup
Fresh install ~60s ~5s 12x faster
Install with cache ~15s ~2s 7.5x faster
Gatsby build ~210s ~207s Similar*
Dev server start ~15s ~12s ~20% faster

*Gatsby uses its own build system (Webpack), so build time is similar. Projects using Bun's native bundler see much bigger speedups (2-10x faster).

Rollback Plan

If you need to rollback:

  1. Restore package-lock.json from git
  2. Delete bun.lock
  3. Run npm install
  4. Revert Dockerfile and CI/CD changes

Additional Resources

Notes

  • Bun is API-compatible with Node.js - no code changes needed
  • Works with all major frameworks (Next.js, Gatsby, Vite, etc.)
  • Can run .js, .ts, .jsx, .tsx files directly
  • Not all npm packages are tested with Bun - check compatibility for critical dependencies