Skip to content

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:

sh
# 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:

sh
# 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

sh
bunup --entry.main src/index.ts --entry.api src/api/v1/index.ts --entry.nested/utils src/utils.ts

Using a Configuration File

typescript
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

sh
# 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

typescript
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":

FormatJavaScript ExtensionTypeScript 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:

FormatJavaScript ExtensionTypeScript 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:

typescript
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 format
  • packageType: The package.json "type" field value (typically 'module' or 'commonjs')
  • options: The complete resolved build options object
  • entry: 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:

typescript
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:

sh
# 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:

typescript
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

sh
# 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

typescript
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

sh
# 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

typescript
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

sh
# Enable code splitting
bunup src/index.ts --splitting

# Disable code splitting
bunup src/index.ts --splitting=false

Using a Configuration File

typescript
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:

sh
# 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

sh
# 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

typescript
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.

sh
# 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:

sh
# 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.

typescript
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.

You can add custom text to the beginning and end of your bundle files:

sh
# 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:

typescript
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:

typescript
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:

sh
# 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:

Input
js
import logo from './logo.svg';
console.log(logo);
Output without publicPath
js
var logo = './logo-a7305bdef.svg';
console.log(logo);
Output with publicPath
js
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:

CLI
sh
# 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_*
typescript
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:

ValueBehavior
"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:

sh
# 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.js
  • browser: Optimized for browsers
  • bun: 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:

sh
# 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:

sh
# 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:

typescript
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:

typescript
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:

sh
bunup src/index.ts --onSuccess "echo 'Build done!' && node scripts/post-build.js"

INFO

In watch mode, onSuccess runs after each rebuild.

Released under the MIT License.