Skip to content

/commands/bun/bun-build

bun build ./index.ts --outdir ./out: bundle with Bun

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
Bun
versions
Bun 1.x
os
any

bun build ./index.ts --outdir ./out bundles the entry file and everything it imports into out/index.js, stripping TypeScript types and resolving node_modules. The default target is the browser; add --target bun or --target node for server code, --minify for production, and --compile to produce a single native executable that includes the Bun runtime.

Example

bash
cat > greet.ts <<'EOF'
export const greet = (name: string): string => `hello ${name}`;
EOF
cat > index.ts <<'EOF'
import { greet } from "./greet";
console.log(greet("bun"));
EOF
npx --yes bun@1 build ./index.ts --outdir ./out > /dev/null 2>&1
echo "--- out/index.js"
cat out/index.js
npx --yes bun@1 build ./index.ts --outdir ./min --minify > /dev/null 2>&1
echo "--- min/index.js"
cat min/index.js
echo
node out/index.js

Output

--- out/index.js
// greet.ts
var greet = (name) => `hello ${name}`;

// index.ts
console.log(greet("bun"));
--- min/index.js
var o=(e)=>`hello ${e}`;console.log(o("bun"));

hello bun

Both modules end up in one file, and the type annotations are gone, so the output runs in Node.js or a browser.

Types are stripped, not checked

bash
cat > bad.ts <<'EOF'
const n: number = "not a number";
console.log(n);
EOF
npx --yes bun@1 build ./bad.ts --outfile bad.js --target node > /dev/null 2>&1
echo "build exit=$?"
cat bad.js

Output

build exit=0
// bad.ts
var n = "not a number";
console.log(n);

The build succeeds although the code assigns a string to a number. Like esbuild and other fast bundlers, Bun transpiles TypeScript without running the type checker. Add --check to type-check the entry points and everything they import (nothing is bundled if there are type errors), or keep tsc --noEmit as a separate CI step.

Main options

OptionEffect
--outdir DIRWrite output files to DIR (required with several entry points)
--outfile FILEWrite a single output file
--target browser|bun|nodeEnvironment the bundle runs in (default browser)
--format esm|cjs|iifeModule format of the output (default esm)
--minifyMinify whitespace, identifiers and syntax
--sourcemap=linked|inline|externalEmit a source map
--splittingShare code between entry points in chunks
--external PKGLeave an import unbundled (repeatable)
--compileBuild a standalone executable with --outfile
--packages externalDo not bundle anything from node_modules
--watchRebuild when a source file changes
--define KEY=VALUEReplace a global identifier with a constant at build time
--env inlineReplace process.env.NAME with the current values (or --env PREFIX_* for a subset)

Choosing a target

--targetResolution and output
browser (default)Prefers the browser export condition; node:path and similar imports work, but calls such as fs.readFile do not
bunFor code that runs in Bun; adds a // @bun pragma so Bun skips re-transpiling. Default when the entry has a #!/usr/bin/env bun shebang
nodePrefers the node export condition and emits code for Node.js

A server bundle built with the default browser target can pick up browser builds of dependencies or fail at run time on Node.js APIs, so set the target explicitly for anything that does not run in a browser.

Standalone executable

bash
bun build ./cli.ts --compile --outfile mycli
./mycli

The executable embeds the Bun runtime, so it is tens of megabytes and runs on machines without Bun. Use --target=bun-linux-x64, bun-darwin-arm64 or bun-windows-x64 to cross-compile for another platform.

FAQ

Does bun build check TypeScript types?

Not by default: it removes type annotations and bundles the code even when it has type errors. Recent Bun versions add --check, which type-checks the entry points and bundles nothing if there are errors. bun build never generates .d.ts declaration files; use tsc for those.

Do I need bun build to run a TypeScript server with Bun?

No. bun index.ts runs the source directly. Bundling with --target bun is optional and mainly reduces startup time or produces a single file to deploy.

How do I keep node_modules out of the bundle?

Pass --packages external to leave every package import unbundled, or --external PKG for specific ones. The output then needs those packages installed where it runs.

Sources