docs(bundler): add comprehensive Bun.build compile API documentation (#25536)

This commit is contained in:
robobun
2025-12-15 16:20:50 -08:00
committed by GitHub
parent dcc3386611
commit 5a8cdc08f0

View File

@@ -5,18 +5,28 @@ description: "Generate standalone executables from TypeScript or JavaScript file
Bun's bundler implements a `--compile` flag for generating a standalone binary from a TypeScript or JavaScript file.
<CodeGroup>
```bash terminal icon="terminal"
bun build ./cli.ts --compile --outfile mycli
```
<Tabs>
<Tab title="CLI">
```bash terminal icon="terminal"
bun build ./cli.ts --compile --outfile mycli
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./cli.ts"],
compile: {
outfile: "./mycli",
},
});
```
</Tab>
</Tabs>
```ts cli.ts icon="/icons/typescript.svg"
console.log("Hello world!");
```
</CodeGroup>
This bundles `cli.ts` into an executable that can be executed directly:
```bash terminal icon="terminal"
@@ -37,49 +47,157 @@ The `--target` flag lets you compile your standalone executable for a different
To build for Linux x64 (most servers):
```bash icon="terminal" terminal
bun build --compile --target=bun-linux-x64 ./index.ts --outfile myapp
<Tabs>
<Tab title="CLI">
```bash icon="terminal" terminal
bun build --compile --target=bun-linux-x64 ./index.ts --outfile myapp
# To support CPUs from before 2013, use the baseline version (nehalem)
bun build --compile --target=bun-linux-x64-baseline ./index.ts --outfile myapp
# To support CPUs from before 2013, use the baseline version (nehalem)
bun build --compile --target=bun-linux-x64-baseline ./index.ts --outfile myapp
# To explicitly only support CPUs from 2013 and later, use the modern version (haswell)
# modern is faster, but baseline is more compatible.
bun build --compile --target=bun-linux-x64-modern ./index.ts --outfile myapp
```
# To explicitly only support CPUs from 2013 and later, use the modern version (haswell)
# modern is faster, but baseline is more compatible.
bun build --compile --target=bun-linux-x64-modern ./index.ts --outfile myapp
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
// Standard Linux x64
await Bun.build({
entrypoints: ["./index.ts"],
compile: {
target: "bun-linux-x64",
outfile: "./myapp",
},
});
// Baseline (pre-2013 CPUs)
await Bun.build({
entrypoints: ["./index.ts"],
compile: {
target: "bun-linux-x64-baseline",
outfile: "./myapp",
},
});
// Modern (2013+ CPUs, faster)
await Bun.build({
entrypoints: ["./index.ts"],
compile: {
target: "bun-linux-x64-modern",
outfile: "./myapp",
},
});
```
</Tab>
</Tabs>
To build for Linux ARM64 (e.g. Graviton or Raspberry Pi):
```bash icon="terminal" terminal
# Note: the default architecture is x64 if no architecture is specified.
bun build --compile --target=bun-linux-arm64 ./index.ts --outfile myapp
```
<Tabs>
<Tab title="CLI">
```bash icon="terminal" terminal
# Note: the default architecture is x64 if no architecture is specified.
bun build --compile --target=bun-linux-arm64 ./index.ts --outfile myapp
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./index.ts"],
compile: {
target: "bun-linux-arm64",
outfile: "./myapp",
},
});
```
</Tab>
</Tabs>
To build for Windows x64:
```bash icon="terminal" terminal
bun build --compile --target=bun-windows-x64 ./path/to/my/app.ts --outfile myapp
<Tabs>
<Tab title="CLI">
```bash icon="terminal" terminal
bun build --compile --target=bun-windows-x64 ./path/to/my/app.ts --outfile myapp
# To support CPUs from before 2013, use the baseline version (nehalem)
bun build --compile --target=bun-windows-x64-baseline ./path/to/my/app.ts --outfile myapp
# To support CPUs from before 2013, use the baseline version (nehalem)
bun build --compile --target=bun-windows-x64-baseline ./path/to/my/app.ts --outfile myapp
# To explicitly only support CPUs from 2013 and later, use the modern version (haswell)
bun build --compile --target=bun-windows-x64-modern ./path/to/my/app.ts --outfile myapp
# To explicitly only support CPUs from 2013 and later, use the modern version (haswell)
bun build --compile --target=bun-windows-x64-modern ./path/to/my/app.ts --outfile myapp
# note: if no .exe extension is provided, Bun will automatically add it for Windows executables
```
# note: if no .exe extension is provided, Bun will automatically add it for Windows executables
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
// Standard Windows x64
await Bun.build({
entrypoints: ["./path/to/my/app.ts"],
compile: {
target: "bun-windows-x64",
outfile: "./myapp", // .exe added automatically
},
});
// Baseline or modern variants
await Bun.build({
entrypoints: ["./path/to/my/app.ts"],
compile: {
target: "bun-windows-x64-baseline",
outfile: "./myapp",
},
});
```
</Tab>
</Tabs>
To build for macOS arm64:
```bash icon="terminal" terminal
bun build --compile --target=bun-darwin-arm64 ./path/to/my/app.ts --outfile myapp
```
<Tabs>
<Tab title="CLI">
```bash icon="terminal" terminal
bun build --compile --target=bun-darwin-arm64 ./path/to/my/app.ts --outfile myapp
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./path/to/my/app.ts"],
compile: {
target: "bun-darwin-arm64",
outfile: "./myapp",
},
});
```
</Tab>
</Tabs>
To build for macOS x64:
```bash icon="terminal" terminal
bun build --compile --target=bun-darwin-x64 ./path/to/my/app.ts --outfile myapp
```
<Tabs>
<Tab title="CLI">
```bash icon="terminal" terminal
bun build --compile --target=bun-darwin-x64 ./path/to/my/app.ts --outfile myapp
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./path/to/my/app.ts"],
compile: {
target: "bun-darwin-x64",
outfile: "./myapp",
},
});
```
</Tab>
</Tabs>
### Supported targets
@@ -110,9 +228,27 @@ The order of the `--target` flag does not matter, as long as they're delimited b
Use the `--define` flag to inject build-time constants into your executable, such as version numbers, build timestamps, or configuration values:
```bash icon="terminal" terminal
bun build --compile --define BUILD_VERSION='"1.2.3"' --define BUILD_TIME='"2024-01-15T10:30:00Z"' src/cli.ts --outfile mycli
```
<Tabs>
<Tab title="CLI">
```bash icon="terminal" terminal
bun build --compile --define BUILD_VERSION='"1.2.3"' --define BUILD_TIME='"2024-01-15T10:30:00Z"' src/cli.ts --outfile mycli
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./src/cli.ts"],
compile: {
outfile: "./mycli",
},
define: {
BUILD_VERSION: JSON.stringify("1.2.3"),
BUILD_TIME: JSON.stringify("2024-01-15T10:30:00Z"),
},
});
```
</Tab>
</Tabs>
These constants are embedded directly into your compiled binary at build time, providing zero runtime overhead and enabling dead code elimination optimizations.
@@ -133,17 +269,50 @@ With compiled executables, you can move that cost from runtime to build-time.
When deploying to production, we recommend the following:
```bash icon="terminal" terminal
bun build --compile --minify --sourcemap ./path/to/my/app.ts --outfile myapp
```
<Tabs>
<Tab title="CLI">
```bash icon="terminal" terminal
bun build --compile --minify --sourcemap ./path/to/my/app.ts --outfile myapp
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./path/to/my/app.ts"],
compile: {
outfile: "./myapp",
},
minify: true,
sourcemap: "linked",
});
```
</Tab>
</Tabs>
### Bytecode compilation
To improve startup time, enable bytecode compilation:
```bash icon="terminal" terminal
bun build --compile --minify --sourcemap --bytecode ./path/to/my/app.ts --outfile myapp
```
<Tabs>
<Tab title="CLI">
```bash icon="terminal" terminal
bun build --compile --minify --sourcemap --bytecode ./path/to/my/app.ts --outfile myapp
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./path/to/my/app.ts"],
compile: {
outfile: "./myapp",
},
minify: true,
sourcemap: "linked",
bytecode: true,
});
```
</Tab>
</Tabs>
Using bytecode compilation, `tsc` starts 2x faster:
@@ -172,9 +341,24 @@ The `--bytecode` argument enables bytecode compilation. Every time you run JavaS
**`--compile-exec-argv="args"`** - Embed runtime arguments that are available via `process.execArgv`:
```bash icon="terminal" terminal
bun build --compile --compile-exec-argv="--smol --user-agent=MyBot" ./app.ts --outfile myapp
```
<Tabs>
<Tab title="CLI">
```bash icon="terminal" terminal
bun build --compile --compile-exec-argv="--smol --user-agent=MyBot" ./app.ts --outfile myapp
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./app.ts"],
compile: {
execArgv: ["--smol", "--user-agent=MyBot"],
outfile: "./myapp",
},
});
```
</Tab>
</Tabs>
```ts app.ts icon="/icons/typescript.svg"
// In the compiled app
@@ -213,35 +397,39 @@ bun build --compile --compile-autoload-tsconfig --compile-autoload-package-json
To disable `.env` or `bunfig.toml` loading for deterministic execution:
```bash icon="terminal" terminal
# Disable .env loading
bun build --compile --no-compile-autoload-dotenv ./app.ts --outfile myapp
<Tabs>
<Tab title="CLI">
```bash icon="terminal" terminal
# Disable .env loading
bun build --compile --no-compile-autoload-dotenv ./app.ts --outfile myapp
# Disable bunfig.toml loading
bun build --compile --no-compile-autoload-bunfig ./app.ts --outfile myapp
# Disable bunfig.toml loading
bun build --compile --no-compile-autoload-bunfig ./app.ts --outfile myapp
# Disable all config loading
bun build --compile --no-compile-autoload-dotenv --no-compile-autoload-bunfig ./app.ts --outfile myapp
```
# Disable all config loading
bun build --compile --no-compile-autoload-dotenv --no-compile-autoload-bunfig ./app.ts --outfile myapp
```
### JavaScript API
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./app.ts"],
compile: {
// tsconfig.json and package.json are disabled by default
autoloadTsconfig: true, // Enable tsconfig.json loading
autoloadPackageJson: true, // Enable package.json loading
You can also configure autoloading via the JavaScript API:
// .env and bunfig.toml are enabled by default
autoloadDotenv: false, // Disable .env loading
autoloadBunfig: false, // Disable bunfig.toml loading
outfile: "./myapp",
},
});
```
```ts
await Bun.build({
entrypoints: ["./app.ts"],
compile: {
// tsconfig.json and package.json are disabled by default
autoloadTsconfig: true, // Enable tsconfig.json loading
autoloadPackageJson: true, // Enable package.json loading
// .env and bunfig.toml are enabled by default
autoloadDotenv: false, // Disable .env loading
autoloadBunfig: false, // Disable bunfig.toml loading
},
});
```
</Tab>
</Tabs>
---
@@ -340,9 +528,23 @@ body {
To build this into a single executable:
```bash terminal icon="terminal"
bun build --compile ./server.ts --outfile myapp
```
<Tabs>
<Tab title="CLI">
```bash terminal icon="terminal"
bun build --compile ./server.ts --outfile myapp
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./server.ts"],
compile: {
outfile: "./myapp",
},
});
```
</Tab>
</Tabs>
This creates a self-contained binary that includes:
@@ -365,11 +567,25 @@ For more details on building full-stack applications with Bun, see the [full-sta
## Worker
To use workers in a standalone executable, add the worker's entrypoint to the CLI arguments:
To use workers in a standalone executable, add the worker's entrypoint to the build:
```bash terminal icon="terminal"
bun build --compile ./index.ts ./my-worker.ts --outfile myapp
```
<Tabs>
<Tab title="CLI">
```bash terminal icon="terminal"
bun build --compile ./index.ts ./my-worker.ts --outfile myapp
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./index.ts", "./my-worker.ts"],
compile: {
outfile: "./myapp",
},
});
```
</Tab>
</Tabs>
Then, reference the worker in your code:
@@ -590,11 +806,32 @@ Unfortunately, if you're using `@mapbox/node-pre-gyp` or other similar tools, yo
### Embed directories
To embed a directory with `bun build --compile`, use a shell glob in your `bun build` command:
To embed a directory with `bun build --compile`, include file patterns in your build:
```bash terminal icon="terminal"
bun build --compile ./index.ts ./public/**/*.png
```
<Tabs>
<Tab title="CLI">
```bash terminal icon="terminal"
bun build --compile ./index.ts ./public/**/*.png
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
import { Glob } from "bun";
// Expand glob pattern to file list
const glob = new Glob("./public/**/*.png");
const pngFiles = Array.from(glob.scanSync("."));
await Bun.build({
entrypoints: ["./index.ts", ...pngFiles],
compile: {
outfile: "./myapp",
},
});
```
</Tab>
</Tabs>
Then, you can reference the files in your code:
@@ -670,26 +907,118 @@ serve({
By default, embedded files have a content hash appended to their name. This is useful for situations where you want to serve the file from a URL or CDN and have fewer cache invalidation issues. But sometimes, this is unexpected and you might want the original name instead:
To disable the content hash, pass `--asset-naming` to `bun build --compile` like this:
To disable the content hash, configure asset naming:
```bash terminal icon="terminal"
bun build --compile --asset-naming="[name].[ext]" ./index.ts
```
<Tabs>
<Tab title="CLI">
```bash terminal icon="terminal"
bun build --compile --asset-naming="[name].[ext]" ./index.ts
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./index.ts"],
compile: {
outfile: "./myapp",
},
naming: {
asset: "[name].[ext]",
},
});
```
</Tab>
</Tabs>
---
## Minification
To trim down the size of the executable a little, pass `--minify` to `bun build --compile`. This uses Bun's minifier to reduce the code size. Overall though, Bun's binary is still way too big and we need to make it smaller.
To trim down the size of the executable, enable minification:
<Tabs>
<Tab title="CLI">
```bash terminal icon="terminal"
bun build --compile --minify ./index.ts --outfile myapp
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./index.ts"],
compile: {
outfile: "./myapp",
},
minify: true, // Enable all minification
});
// Or granular control:
await Bun.build({
entrypoints: ["./index.ts"],
compile: {
outfile: "./myapp",
},
minify: {
whitespace: true,
syntax: true,
identifiers: true,
},
});
```
</Tab>
</Tabs>
This uses Bun's minifier to reduce the code size. Overall though, Bun's binary is still way too big and we need to make it smaller.
---
## Windows-specific flags
When compiling a standalone executable on Windows, there are two platform-specific options that can be used to customize metadata on the generated `.exe` file:
When compiling a standalone executable on Windows, there are platform-specific options to customize metadata on the generated `.exe` file:
- `--windows-icon=path/to/icon.ico` to customize the executable file icon.
- `--windows-hide-console` to disable the background terminal, which can be used for applications that do not need a TTY.
<Tabs>
<Tab title="CLI">
```bash terminal icon="terminal"
# Custom icon
bun build --compile --windows-icon=path/to/icon.ico ./app.ts --outfile myapp
# Hide console window (for GUI apps)
bun build --compile --windows-hide-console ./app.ts --outfile myapp
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./app.ts"],
compile: {
outfile: "./myapp",
windows: {
icon: "./path/to/icon.ico",
hideConsole: true,
// Additional Windows metadata:
title: "My Application",
publisher: "My Company",
version: "1.0.0",
description: "A standalone Windows application",
copyright: "Copyright 2024",
},
},
});
```
</Tab>
</Tabs>
Available Windows options:
- `icon` - Path to `.ico` file for the executable icon
- `hideConsole` - Disable the background terminal (for GUI apps)
- `title` - Application title in file properties
- `publisher` - Publisher name in file properties
- `version` - Version string in file properties
- `description` - Description in file properties
- `copyright` - Copyright notice in file properties
<Warning>These flags currently cannot be used when cross-compiling because they depend on Windows APIs.</Warning>
@@ -746,9 +1075,23 @@ codesign -vvv --verify ./myapp
Standalone executables support code splitting. Use `--compile` with `--splitting` to create an executable that loads code-split chunks at runtime.
```bash
bun build --compile --splitting ./src/entry.ts --outdir ./build
```
<Tabs>
<Tab title="CLI">
```bash terminal icon="terminal"
bun build --compile --splitting ./src/entry.ts --outdir ./build
```
</Tab>
<Tab title="JavaScript">
```ts build.ts icon="/icons/typescript.svg"
await Bun.build({
entrypoints: ["./src/entry.ts"],
compile: true,
splitting: true,
outdir: "./build",
});
```
</Tab>
</Tabs>
<CodeGroup>
@@ -777,6 +1120,50 @@ Lazy module loaded
---
## Using plugins
Plugins work with standalone executables, allowing you to transform files during the build process:
```ts build.ts icon="/icons/typescript.svg"
import type { BunPlugin } from "bun";
const envPlugin: BunPlugin = {
name: "env-loader",
setup(build) {
build.onLoad({ filter: /\.env\.json$/ }, async args => {
// Transform .env.json files into validated config objects
const env = await Bun.file(args.path).json();
return {
contents: `export default ${JSON.stringify(env)};`,
loader: "js",
};
});
},
};
await Bun.build({
entrypoints: ["./cli.ts"],
compile: {
outfile: "./mycli",
},
plugins: [envPlugin],
});
```
Example use case - embedding environment config at build time:
```ts cli.ts icon="/icons/typescript.svg"
import config from "./config.env.json";
console.log(`Running in ${config.environment} mode`);
console.log(`API endpoint: ${config.apiUrl}`);
```
Plugins can perform any transformation: compile YAML/TOML configs, inline SQL queries, generate type-safe API clients, or preprocess templates. Refer to the [plugin documentation](/bundler/plugins) for more details.
---
## Unsupported CLI arguments
Currently, the `--compile` flag can only accept a single entrypoint at a time and does not support the following flags:
@@ -785,3 +1172,106 @@ Currently, the `--compile` flag can only accept a single entrypoint at a time an
- `--public-path`
- `--target=node` or `--target=browser`
- `--no-bundle` - we always bundle everything into the executable.
---
## API reference
The `compile` option in `Bun.build()` accepts three forms:
```ts title="types" icon="/icons/typescript.svg"
interface BuildConfig {
entrypoints: string[];
compile: boolean | Bun.Build.Target | CompileBuildOptions;
// ... other BuildConfig options (minify, sourcemap, define, plugins, etc.)
}
interface CompileBuildOptions {
target?: Bun.Build.Target; // Cross-compilation target
outfile?: string; // Output executable path
execArgv?: string[]; // Runtime arguments (process.execArgv)
autoloadTsconfig?: boolean; // Load tsconfig.json (default: false)
autoloadPackageJson?: boolean; // Load package.json (default: false)
autoloadDotenv?: boolean; // Load .env files (default: true)
autoloadBunfig?: boolean; // Load bunfig.toml (default: true)
windows?: {
icon?: string; // Path to .ico file
hideConsole?: boolean; // Hide console window
title?: string; // Application title
publisher?: string; // Publisher name
version?: string; // Version string
description?: string; // Description
copyright?: string; // Copyright notice
};
}
```
Usage forms:
```ts icon="/icons/typescript.svg"
// Simple boolean - compile for current platform (uses entrypoint name as output)
compile: true
// Target string - cross-compile (uses entrypoint name as output)
compile: "bun-linux-x64"
// Full options object - specify outfile and other options
compile: {
target: "bun-linux-x64",
outfile: "./myapp",
}
```
### Supported targets
```ts title="Bun.Build.Target" icon="/icons/typescript.svg"
type Target =
| "bun-darwin-x64"
| "bun-darwin-x64-baseline"
| "bun-darwin-arm64"
| "bun-linux-x64"
| "bun-linux-x64-baseline"
| "bun-linux-x64-modern"
| "bun-linux-arm64"
| "bun-linux-x64-musl"
| "bun-linux-arm64-musl"
| "bun-windows-x64"
| "bun-windows-x64-baseline"
| "bun-windows-x64-modern";
```
### Complete example
```ts build.ts icon="/icons/typescript.svg"
import type { BunPlugin } from "bun";
const myPlugin: BunPlugin = {
name: "my-plugin",
setup(build) {
// Plugin implementation
},
};
const result = await Bun.build({
entrypoints: ["./src/cli.ts"],
compile: {
target: "bun-linux-x64",
outfile: "./dist/mycli",
execArgv: ["--smol"],
autoloadDotenv: false,
autoloadBunfig: false,
},
minify: true,
sourcemap: "linked",
bytecode: true,
define: {
"process.env.NODE_ENV": JSON.stringify("production"),
VERSION: JSON.stringify("1.0.0"),
},
plugins: [myPlugin],
});
if (result.success) {
console.log("Build successful:", result.outputs[0].path);
}
```