Options
Bunup provides a rich set of options to customize your build. See the table of contents on the right side to quickly navigate to the option you are looking for.
Entry Points
Bunup supports multiple ways to define entry points. Entry points are the source files that Bunup will use as starting points for bundling.
Single Entry Point
The simplest way to define an entry point is to provide a single file path:
# CLI
bunup src/index.ts
# Configuration file
export default defineConfig({
entry: 'src/index.ts',
});
This will generate an output file named after the input file (e.g., dist/index.js
).
Multiple Entry Points
You can specify multiple entry points in several ways:
# CLI (method 1)
bunup src/index.ts src/cli.ts
# CLI (method 2)
bunup --entry src/index.ts --entry src/cli.ts
# Configuration file
export default defineConfig({
entry: ['src/index.ts', 'src/cli.ts'],
});
This will generate output files named after each input file (e.g., dist/index.js
and dist/cli.js
).
Named Entries
Named entries allow you to specify custom output filenames.
Using the CLI
bunup --entry.main src/index.ts --entry.api src/api/v1/index.ts --entry.nested/utils src/utils.ts
Using a Configuration File
export default defineConfig({
entry: {
main: 'src/index.ts', // Outputs to dist/main.js
api: 'src/api/v1/index.ts', // Outputs to dist/api.js
'nested/utils': 'src/utils.ts', // Outputs to dist/nested/utils.js
},
});
This will generate output files with the specified names (e.g., dist/main.js
from src/index.ts
).
Output Formats
Bunup supports three output formats:
- esm: ECMAScript modules
- cjs: CommonJS modules
- iife: Immediately Invoked Function Expression
You can specify one or more formats:
Using the CLI
# Single format
bunup src/index.ts --format esm
# Multiple formats (comma-separated, no spaces)
bunup src/index.ts --format esm,cjs,iife
Using a Configuration File
export default defineConfig({
entry: ['src/index.ts'],
// Single format
format: ['esm'],
// Or multiple formats
// format: ['esm', 'cjs', 'iife'],
});
Output File Extensions
The file extensions are determined automatically based on the format and your package.json type
field:
When package.json has "type": "module"
:
Format | JavaScript Extension | TypeScript Declaration Extension |
---|---|---|
esm | .js | .d.ts |
cjs | .cjs | .d.cts |
iife | .global.js | .global.d.ts |
When package.json has "type": "commonjs"
or is unspecified:
Format | JavaScript Extension | TypeScript Declaration Extension |
---|---|---|
esm | .mjs | .d.mts |
cjs | .js | .d.ts |
iife | .global.js | .global.d.ts |
Customizing Output Extensions
You can customize the output file extensions using the outputExtension
option:
export default defineConfig({
entry: ['src/index.ts', 'src/worker/index.ts'],
format: ['esm', 'cjs'],
outputExtension: ({ format, entry }) => ({
js: entry === 'src/worker/index.ts' ? '.worker.js' : `.${format}.js`,
}),
});
The outputExtension
function receives:
format
: The output formatpackageType
: The package.json "type" field value (typically 'module' or 'commonjs')options
: The complete resolved build options objectentry
: The entry which is the same as what you defined in the entry option
It should return an object with:
js
: The JavaScript file extension (including the leading dot)dts
: The TypeScript declaration file extension (including the leading dot)
Both extensions can be customized independently. For example:
outputExtension: ({ format, entry }) => ({
js: entry === 'src/worker/index.ts' ? '.worker.js' : `.${format}.js`,
dts: entry === 'src/worker/index.ts' ? '.worker.d.ts' : `.${format}.d.ts`
})
Named Configurations
You can give your build configurations names for better logging:
# CLI
bunup src/index.ts --name my-library
# Configuration file
export default defineConfig({
name: 'my-library',
entry: ['src/index.ts'],
});
This is especially useful when you have multiple configurations:
export default defineConfig([
{
name: 'node-build',
entry: ['src/index.ts'],
format: ['cjs'],
target: 'node',
},
{
name: 'browser-build',
entry: ['src/index.ts'],
format: ['esm', 'iife'],
target: 'browser',
},
]);
Customizing Dependency Bundling
By default, Bunup treats all packages listed in your package.json
under dependencies
and peerDependencies
as external. This means:
dependencies
will be installed automatically when your package is installed.peerDependencies
are expected to be installed by the end user.
These external packages are not included in your final bundle.
However, any modules listed in devDependencies
or others will be bundled.
External Dependencies
You can explicitly mark any package as external, even if it's not listed in dependencies
or peerDependencies
.
Using the CLI
# Mark a single package as external
bunup src/index.ts --external lodash
# Mark multiple packages (comma-separated, no spaces)
bunup src/index.ts --external lodash,react,react-dom
Using a Configuration File
export default defineConfig({
entry: ['src/index.ts'],
external: ['lodash', 'react', '@some/package'],
});
Forcing External Packages to Be Bundled
Sometimes, you may want to include specific modules in your bundle, even if they're marked as external (e.g., part of dependencies
or peerDependencies
).
Using the CLI
# Mark lodash as external, but include lodash/merge in the bundle
bunup src/index.ts --external lodash --no-external lodash/merge
Using a Configuration File
export default defineConfig({
entry: ['src/index.ts'],
external: ['lodash'],
noExternal: ['lodash/merge'], // This will be bundled
});
INFO
Both external
and noExternal
support exact strings and regular expressions.
Code Splitting
Code splitting allows Bunup to split your code into multiple chunks for better performance and caching.
Default Behavior
- Code splitting is enabled by default for ESM format
- Code splitting is disabled by default for CJS and IIFE formats
Configuring Code Splitting
You can explicitly enable or disable code splitting:
Using the CLI
# Enable code splitting
bunup src/index.ts --splitting
# Disable code splitting
bunup src/index.ts --splitting=false
Using a Configuration File
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
// Enable for all formats
splitting: true,
// Or disable for all formats
// splitting: false,
});
Minification
Bunup provides several minification options to reduce the size of your output files.
Basic Minification
To enable all minification options:
# CLI
bunup src/index.ts --minify
# Configuration file
export default defineConfig({
entry: ['src/index.ts'],
minify: true,
});
Granular Minification Control
You can configure individual minification options:
Using the CLI
# Minify whitespace only
bunup src/index.ts --minify-whitespace
# Minify whitespace and syntax, but not identifiers
bunup src/index.ts --minify-whitespace --minify-syntax
Using a Configuration File
export default defineConfig({
entry: ['src/index.ts'],
// Configure individual options
minifyWhitespace: true,
minifyIdentifiers: false,
minifySyntax: true,
});
The minify
option is a shorthand that enables all three specific options. If you set individual options, they take precedence over the minify
setting.
Bytecode
Bunup can generate bytecode for your JavaScript/TypeScript entrypoints, which can significantly improve startup times for large applications.
# CLI
bunup src/index.ts --bytecode --target bun
# Configuration file
export default defineConfig({
entry: ['src/index.ts'],
bytecode: true,
target: 'bun', # Bytecode compilation requires "bun" target
});
For more information, see the Bun documentation on bytecode and Bun's blog post on bytecode compilation.
Source Maps
Bunup can generate source maps for your bundled code:
# CLI
bunup src/index.ts --sourcemap linked
# Or just use --sourcemap for inline source maps
bunup src/index.ts --sourcemap
# Configuration file
export default defineConfig({
entry: ['src/index.ts'],
sourcemap: 'linked'
# Can also use boolean
# sourcemap: true // equivalent to 'inline'
});
Available sourcemap values:
none
linked
external
inline
true
(equivalent to 'inline')
For detailed explanations of these values, see the Bun documentation on source maps.
Define Global Constants
Bunup allows you to define global constants that will be replaced at build time. This is useful for feature flags, version numbers, or any other build-time constants.
export default defineConfig({
entry: ['src/index.ts'],
define: {
PACKAGE_VERSION: '"1.0.0"',
DEBUG: 'false',
},
});
The define
option takes an object where:
- Keys are the identifiers to replace
- Values are the strings to replace them with
For more information on how define works, see the Bun documentation on define.
Banner and Footer
You can add custom text to the beginning and end of your bundle files:
# CLI
bunup src/index.ts --banner 'use client' --footer '// built with love in SF'
# Configuration file
export default defineConfig({
entry: ['src/index.ts'],
# Add text to the beginning of bundle files
banner: '"use client";',
# Add text to the end of bundle files
footer: '// built with love in SF',
});
The banner
option adds text to the beginning of the bundle, useful for directives like "use client" for React or license information.
The footer
option adds text to the end of the bundle, which can be used for license information or other closing comments.
For more information, see the Bun documentation on banner and footer.
Drop Function Calls
You can remove specific function calls from your bundle:
export default defineConfig({
entry: ['src/index.ts'],
drop: ['console', 'debugger', 'anyIdentifier.or.propertyAccess'],
});
The drop
option removes function calls specified in the array. For example, drop: ["console"]
will remove all calls to console.log
. Arguments to calls will also be removed, regardless of if those arguments may have side effects. Dropping debugger
will remove all debugger
statements.
For more information, see the Bun documentation on drop.
Custom Loaders
You can configure how different file types are loaded:
export default defineConfig({
entry: ['src/index.ts'],
loader: {
'.png': 'dataurl',
'.txt': 'file',
},
});
The loader
option takes a map of file extensions to built-in loader names, allowing you to customize how different file types are processed during bundling.
For more information, see the Bun documentation on loaders.
Public Path
You can specify a prefix to be added to specific import paths in your bundled code:
# CLI
bunup src/index.ts --public-path https://cdn.example.com/
# Configuration file
export default defineConfig({
entry: ['src/index.ts'],
publicPath: 'https://cdn.example.com/',
});
The publicPath
option only affects certain types of imports in the final bundle:
- Asset imports (like images or SVG files)
- External modules
- Chunk files when code splitting is enabled
By default, these imports are relative. Setting publicPath
will prefix these specific file paths with the specified value, which is useful for serving assets from a CDN.
For example:
import logo from './logo.svg';
console.log(logo);
var logo = './logo-a7305bdef.svg';
console.log(logo);
var logo = 'https://cdn.example.com/logo-a7305bdef.svg';
console.log(logo);
For more information, see the Bun documentation on publicPath.
Environment Variables
Bunup provides flexible options for handling environment variables in your bundled code:
# Inline all environment variables available at build time
FOO=bar API_KEY=secret bunup src/index.ts --env inline
# Disable all environment variable inlining
bunup src/index.ts --env disable
# Only inline environment variables with a specific prefix (e.g., PUBLIC_)
PUBLIC_URL=https://example.com bunup src/index.ts --env PUBLIC_*
export default defineConfig({
entry: ['src/index.ts'],
// Inline all available environment variables at build time
env: 'inline',
// Or disable inlining entirely (keep process.env.FOO in the output)
// env: "disable",
// Or inline only variables that start with a specific prefix
// env: "PUBLIC_*",
// Or explicitly provide specific environment variables
// These will replace both process.env.FOO and import.meta.env.FOO
// env: {
// API_URL: "https://api.example.com",
// DEBUG: "false",
// },
});
How it Works
The env
option controls how process.env.*
and import.meta.env.*
expressions are replaced at build time:
Value | Behavior |
---|---|
"inline" | Replaces all process.env.VAR references in your code with the actual values of those environment variables at the time of the build. |
"disable" | Disables environment variable replacement. Keeps process.env.VAR as-is in output. |
"PREFIX_*" | Only inlines environment variables matching the given prefix (e.g. PUBLIC_* ). |
{ key: value } | Replaces both process.env.KEY and import.meta.env.KEY with the provided values, regardless of the environment. |
For more information, see the Bun documentation on environment variables.
Target Environments
Bunup allows you to specify the target environment for your bundle:
# CLI
bunup src/index.ts --target browser
# Configuration file
export default defineConfig({
entry: ['src/index.ts'],
target: 'browser',
});
Available targets:
node
(default): Optimized for Node.jsbrowser
: Optimized for browsersbun
: Optimized for the Bun runtime
If a file contains a Bun shebang (#!/usr/bin/env bun
), the bun
target will be used automatically for that file.
Output Directory
You can specify where Bunup should output the bundled files:
# CLI
bunup src/index.ts --out-dir build
# Configuration file
export default defineConfig({
entry: ['src/index.ts'],
outDir: 'build',
});
The default output directory is dist
.
Cleaning the Output Directory
By default, Bunup cleans the output directory before each build. You can disable this behavior:
# CLI
bunup src/index.ts --clean=false
# Configuration file
export default defineConfig({
entry: ['src/index.ts'],
clean: false,
});
Post-build Operations
The onSuccess
callback runs after the build process successfully completes. This is useful for performing custom post-build operations:
export default defineConfig({
entry: ['src/index.ts'],
onSuccess: (options) => {
console.log('Build completed successfully!');
// Perform post-build operations here
// The options parameter contains the build options that were used
},
});
If you enable watch mode, the onSuccess
callback will execute after each successful rebuild. If you want to perform post-build operations only when not in watch mode, you can check the watch
property in the options:
export default defineConfig({
entry: ['src/index.ts'],
onSuccess: (options) => {
if (options.watch) return;
console.log('Build completed! Only running in non-watch mode');
// Perform operations that should only happen in regular builds
},
});
Using CLI
The onSuccess
CLI option allows you to specify a shell command that will be executed after a successful build:
bunup src/index.ts --onSuccess "echo 'Build done!' && node scripts/post-build.js"
INFO
In watch mode, onSuccess
runs after each rebuild.