|$ curl https://forge-ai.dev/api/markdown?path=docs/build-tools/bun-build
$cat docs/bun-build.md
updated Today·22-30 min read·published

Bun Build

Build ToolsBunBundlerIntermediate🎯Free Tools
Introduction

Bun is an all-in-one JavaScript toolkit (runtime, package manager, test runner, bundler). bun build is its native bundler — fast, TypeScript-aware, and useful for browser bundles, server-side bundles, and executables. It competes most directly with esbuild on speed and API simplicity.

Adopt Bun build when your team already runs Bun, or when you want a single binary for transpile+bundle without wiring esbuild. Prefer Vite/Rspack when you need a mature plugin ecosystem, complex CSS pipelines, or Module Federation.

info

Bun the runtime and Bun the bundler are related but separable decisions. You can bundle with Bun and still deploy to Node, or run with Bun and bundle with Vite.
Install Bun
install.sh
Bash
1# macOS / Linux
2curl -fsSL https://bun.sh/install | bash
3
4# Verify
5bun --version
6
7# Project-local scripts still call `bun build` once Bun is on PATH
bun build CLI
cli.sh
Bash
1# Browser-oriented bundle
2bun build ./src/index.ts --outdir=dist --target=browser
3
4# Server / Node-compatible
5bun build ./src/server.ts --outdir=dist --target=node
6
7# Bun runtime target
8bun build ./src/cli.ts --outdir=dist --target=bun
9
10# Minify + sourcemap
11bun build ./src/index.ts --outdir=dist --minify --sourcemap
12
13# Code splitting
14bun build ./src/index.ts --outdir=dist --splitting
15
16# Watch
17bun build ./src/index.ts --outdir=dist --watch
18
19# Compile to a standalone executable (Bun feature)
20bun build ./src/cli.ts --compile --outfile=mycli
Flag / optionPurposeWhen
--targetbrowser / node / bunAlways set explicitly
--minifyShrink production outputProd browser bundles
--sourcemapDebug mappingAlmost always in prod (hidden/upload)
--splittingShared chunk extractionMulti-entry or dynamic import apps
--compileSingle binary CLIDistributing tools without Node install
Programmatic API
build.ts
TypeScript
1const result = await Bun.build({
2 entrypoints: ["./src/index.ts"],
3 outdir: "./dist",
4 target: "browser",
5 minify: true,
6 sourcemap: "external",
7 splitting: true,
8 naming: "[dir]/[name]-[hash].[ext]",
9 define: {
10 "process.env.NODE_ENV": JSON.stringify("production"),
11 },
12 external: ["react", "react-dom"], // for library-like outputs
13});
14
15if (!result.success) {
16 console.error(result.logs);
17 process.exit(1);
18}
19
20for (const output of result.outputs) {
21 console.log(output.path, output.size);
22}
📝

note

Run build scripts with bun run build.ts. The Bun.build API is not available inside plain Node unless you polyfill — keep build scripts Bun-native.
Browser vs Server Bundles

Target selection changes how Bun resolves builtins, polyfills, and module formats.

TargetUse forWatch outs
browserSPA bundles, widgetsDo not pull Node builtins
nodeServices running on NodeExternalize native addons
bunApps that run under BunMay use Bun-only APIs
package.json
JSON
1{
2 "scripts": {
3 "build:web": "bun build ./src/client.ts --outdir=dist/client --target=browser --minify --sourcemap",
4 "build:api": "bun build ./src/server.ts --outdir=dist/server --target=node --sourcemap",
5 "build": "bun run build:web && bun run build:api"
6 }
7}
Minification

--minify reduces identifiers and whitespace. For libraries, prefer unminified dual packages so consumers control minification. For end-user browser apps, minify production builds.

best practice

Always keep source maps for minified production bundles and upload them to your error tracker — never serve maps publicly unless intentional.
Comparison to esbuild
AspectBun buildesbuild
SpeedVery fast (native)Very fast (Go)
EcosystemGrowing with BunWidely embedded (Vite, tsup)
Plugin modelBun pluginsesbuild plugins
Node portabilityNeeds Bun to run builderRuns anywhere Node runs
Extras--compile, tight runtime integrationMature transform API, metafile
Best fitBun-centric stacksTooling inside Vite/tsup/CI Node images
🔥

pro tip

If your only goal is "fast TS library builds on Node CI," tsup/esbuild remains the path of least resistance. Choose Bun build when you already standardize on Bun images and want fewer moving parts.
HTML & Assets

Bun can bundle from HTML entry points and handle many asset types. For complex Tailwind/PostCSS/app shells, Vite still provides a richer DX (plugin ecosystem, framework integrations).

html-entry.sh
Bash
1# HTML as entry (feature set evolves — check current Bun docs)
2bun build ./index.html --outdir=dist --target=browser --minify
CI Considerations
  • Install Bun on runners (oven-sh/setup-bun on GitHub Actions).
  • Cache Bun's install cache / lockfile (bun.lock).
  • Pin Bun version — bundler behavior changes across releases.
  • Do not assume Node can execute Bun.build scripts.
.github/workflows/build.yml
YAML
1jobs:
2 build:
3 runs-on: ubuntu-latest
4 steps:
5 - uses: actions/checkout@v4
6 - uses: oven-sh/setup-bun@v2
7 with:
8 bun-version: "1.2.17"
9 - run: bun install --frozen-lockfile
10 - run: bun run build
Plugins

Bun supports a plugin API for custom loaders (similar in spirit to esbuild plugins). Use plugins sparingly — prefer built-in TypeScript/JSX/JSON support first.

plugin-example.ts
TypeScript
1await Bun.build({
2 entrypoints: ["./src/index.ts"],
3 outdir: "./dist",
4 target: "browser",
5 plugins: [
6 {
7 name: "raw-text",
8 setup(build) {
9 build.onLoad({ filter: /\.txt$/ }, async (args) => {
10 const text = await Bun.file(args.path).text();
11 return {
12 contents: `export default ${JSON.stringify(text)}`,
13 loader: "js",
14 };
15 });
16 },
17 },
18 ],
19});
Library-Style Output

For npm libraries, tsup remains the safer default on Node CI. If you still use Bun, externalize peers and emit formats your exports map expects.

lib-build.ts
TypeScript
1await Bun.build({
2 entrypoints: ["./src/index.ts"],
3 outdir: "./dist",
4 target: "node",
5 format: "esm",
6 external: ["react", "react-dom"],
7 sourcemap: "external",
8});
📝

note

Dual ESM/CJS packaging with full DTS generation is more battle-tested in tsup/Rollup today. Use Bun build for apps and CLIs first; graduate libraries carefully.
When to Use
Use Bun build whenPrefer alternatives when
Team already on Bun runtimeNeed Webpack loaders / federation
Shipping a compiled CLINeed Vite framework templates
Simple fast bundlesNeed Node-only CI without Bun
Prototyping without ViteComplex CSS / SSR frameworks

warning

Production readiness varies by feature (HTML entries, CSS, plugins). Validate your exact pipeline with integration tests before migrating a large app off Vite/Webpack.
$Blueprint — Engineering Documentation·Section ID: BT-BUN-01·Revision: 1.0

Community

Get help on Slack, Discord or VIP

Stuck on a guide? Join the community and ask.