THE FIELD NOTES

Converting from npm to Bun

Step-by-step guide to migrate a Node.js project from npm to Bun for faster builds and dependency management.

Chris House3 min read
Change the runtime workflowA comparison of npm and Bun workflows across dependency installation, scripts, Docker images, and CI validation.NOTE / JAVASCRIPT TOOLINGChange the runtime workflowCHRIS HOUSEchrishouse.io01Dependenciesnpm install → bun install02Project scriptsnpm run → bun run03ContainerNode image → oven/bun image04CI pipelineSetup Bun and test the buildThe migration updates local commands, container images, and CI while validating the existing project.
In this note

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