From 5a8cdc08f0efa114529384d706fa8b1ddfedcf8a Mon Sep 17 00:00:00 2001 From: robobun Date: Mon, 15 Dec 2025 16:20:50 -0800 Subject: [PATCH] docs(bundler): add comprehensive Bun.build compile API documentation (#25536) --- docs/bundler/executables.mdx | 672 ++++++++++++++++++++++++++++++----- 1 file changed, 581 insertions(+), 91 deletions(-) diff --git a/docs/bundler/executables.mdx b/docs/bundler/executables.mdx index ec4314d6df..16c623424f 100644 --- a/docs/bundler/executables.mdx +++ b/docs/bundler/executables.mdx @@ -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. - - -```bash terminal icon="terminal" -bun build ./cli.ts --compile --outfile mycli -``` + + + ```bash terminal icon="terminal" + bun build ./cli.ts --compile --outfile mycli + ``` + + + ```ts build.ts icon="/icons/typescript.svg" + await Bun.build({ + entrypoints: ["./cli.ts"], + compile: { + outfile: "./mycli", + }, + }); + ``` + + ```ts cli.ts icon="/icons/typescript.svg" console.log("Hello world!"); ``` - - 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 + + + ```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 + ``` + + + + ```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", + }, + }); + ``` + + + 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 -``` + + + ```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 + ``` + + + ```ts build.ts icon="/icons/typescript.svg" + await Bun.build({ + entrypoints: ["./index.ts"], + compile: { + target: "bun-linux-arm64", + outfile: "./myapp", + }, + }); + ``` + + To build for Windows x64: -```bash icon="terminal" terminal -bun build --compile --target=bun-windows-x64 ./path/to/my/app.ts --outfile myapp + + + ```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 + ``` + + + + ```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", + }, + }); + ``` + + + To build for macOS arm64: -```bash icon="terminal" terminal -bun build --compile --target=bun-darwin-arm64 ./path/to/my/app.ts --outfile myapp -``` + + + ```bash icon="terminal" terminal + bun build --compile --target=bun-darwin-arm64 ./path/to/my/app.ts --outfile myapp + ``` + + + ```ts build.ts icon="/icons/typescript.svg" + await Bun.build({ + entrypoints: ["./path/to/my/app.ts"], + compile: { + target: "bun-darwin-arm64", + outfile: "./myapp", + }, + }); + ``` + + To build for macOS x64: -```bash icon="terminal" terminal -bun build --compile --target=bun-darwin-x64 ./path/to/my/app.ts --outfile myapp -``` + + + ```bash icon="terminal" terminal + bun build --compile --target=bun-darwin-x64 ./path/to/my/app.ts --outfile myapp + ``` + + + ```ts build.ts icon="/icons/typescript.svg" + await Bun.build({ + entrypoints: ["./path/to/my/app.ts"], + compile: { + target: "bun-darwin-x64", + outfile: "./myapp", + }, + }); + ``` + + ### 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 -``` + + + ```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 + ``` + + + ```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"), + }, + }); + ``` + + 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 -``` + + + ```bash icon="terminal" terminal + bun build --compile --minify --sourcemap ./path/to/my/app.ts --outfile myapp + ``` + + + ```ts build.ts icon="/icons/typescript.svg" + await Bun.build({ + entrypoints: ["./path/to/my/app.ts"], + compile: { + outfile: "./myapp", + }, + minify: true, + sourcemap: "linked", + }); + ``` + + ### 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 -``` + + + ```bash icon="terminal" terminal + bun build --compile --minify --sourcemap --bytecode ./path/to/my/app.ts --outfile myapp + ``` + + + ```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, + }); + ``` + + 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 -``` + + + ```bash icon="terminal" terminal + bun build --compile --compile-exec-argv="--smol --user-agent=MyBot" ./app.ts --outfile myapp + ``` + + + ```ts build.ts icon="/icons/typescript.svg" + await Bun.build({ + entrypoints: ["./app.ts"], + compile: { + execArgv: ["--smol", "--user-agent=MyBot"], + outfile: "./myapp", + }, + }); + ``` + + ```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 + + + ```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 + + + ```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 - }, -}); -``` + + --- @@ -340,9 +528,23 @@ body { To build this into a single executable: -```bash terminal icon="terminal" -bun build --compile ./server.ts --outfile myapp -``` + + + ```bash terminal icon="terminal" + bun build --compile ./server.ts --outfile myapp + ``` + + + ```ts build.ts icon="/icons/typescript.svg" + await Bun.build({ + entrypoints: ["./server.ts"], + compile: { + outfile: "./myapp", + }, + }); + ``` + + 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 -``` + + + ```bash terminal icon="terminal" + bun build --compile ./index.ts ./my-worker.ts --outfile myapp + ``` + + + ```ts build.ts icon="/icons/typescript.svg" + await Bun.build({ + entrypoints: ["./index.ts", "./my-worker.ts"], + compile: { + outfile: "./myapp", + }, + }); + ``` + + 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 -``` + + + ```bash terminal icon="terminal" + bun build --compile ./index.ts ./public/**/*.png + ``` + + + ```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", + }, + }); + ``` + + + 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 -``` + + + ```bash terminal icon="terminal" + bun build --compile --asset-naming="[name].[ext]" ./index.ts + ``` + + + ```ts build.ts icon="/icons/typescript.svg" + await Bun.build({ + entrypoints: ["./index.ts"], + compile: { + outfile: "./myapp", + }, + naming: { + asset: "[name].[ext]", + }, + }); + ``` + + --- ## 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: + + + + ```bash terminal icon="terminal" + bun build --compile --minify ./index.ts --outfile myapp + ``` + + + ```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, + }, + }); + ``` + + + + +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. + + + ```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 + ``` + + + + ```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", + }, + }, + }); + ``` + + + +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 These flags currently cannot be used when cross-compiling because they depend on Windows APIs. @@ -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 -``` + + + ```bash terminal icon="terminal" + bun build --compile --splitting ./src/entry.ts --outdir ./build + ``` + + + ```ts build.ts icon="/icons/typescript.svg" + await Bun.build({ + entrypoints: ["./src/entry.ts"], + compile: true, + splitting: true, + outdir: "./build", + }); + ``` + + @@ -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); +} +```