Bun Bundler
Use this skill when bundling JavaScript/TypeScript applications with Bun's built-in bundler, which provides exceptional performance and modern features.
Key Concepts
Basic Bundling
Bun can bundle your code for different targets:
Bundle for Bun runtime
bun build ./src/index.ts --outdir ./dist
Bundle for browsers
bun build ./src/index.ts --outdir ./dist --target=browser
Bundle for Node.js
bun build ./src/index.ts --outdir ./dist --target=node
Minify output
bun build ./src/index.ts --outdir ./dist --minify
Programmatic API
Use Bun's build API in TypeScript:
import { build } from "bun";
await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", target: "bun", minify: true, sourcemap: "external", });
Build Targets
Bun supports multiple build targets:
-
bun
-
Optimized for Bun runtime (default)
-
browser
-
Browser-compatible bundle
-
node
-
Node.js-compatible bundle
Output Formats
Control output format:
await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", format: "esm", // or "cjs", "iife" });
Best Practices
Entry Points Configuration
Define multiple entry points for complex applications:
await build({ entrypoints: [ "./src/client/index.ts", "./src/server/index.ts", "./src/worker.ts", ], outdir: "./dist", naming: { entry: "[dir]/[name].[ext]", chunk: "[name]-[hash].[ext]", asset: "assets/[name]-[hash].[ext]", }, });
Tree Shaking
Bun automatically tree-shakes unused code:
// utils.ts export function used() { return "used"; }
export function unused() { return "unused"; }
// index.ts import { used } from "./utils";
console.log(used()); // Only 'used' function will be bundled
Code Splitting
Split code for better loading performance:
await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", splitting: true, // Enable code splitting target: "browser", });
Environment Variables
Replace environment variables at build time:
await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", define: { "process.env.API_URL": JSON.stringify("https://api.example.com"), "process.env.NODE_ENV": JSON.stringify("production"), }, });
External Dependencies
Mark dependencies as external to exclude from bundle:
await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", external: ["react", "react-dom"], // Don't bundle React target: "browser", });
Source Maps
Generate source maps for debugging:
await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", sourcemap: "external", // or "inline", "none" minify: true, });
Common Patterns
Building a Library
// build.ts import { build } from "bun";
// ESM build await build({ entrypoints: ["./src/index.ts"], outdir: "./dist/esm", format: "esm", target: "node", minify: true, sourcemap: "external", });
// CJS build await build({ entrypoints: ["./src/index.ts"], outdir: "./dist/cjs", format: "cjs", target: "node", minify: true, sourcemap: "external", });
console.log("Build complete!");
Building a Web Application
// build.ts import { build } from "bun";
await build({ entrypoints: ["./src/index.tsx"], outdir: "./dist", target: "browser", format: "esm", minify: true, splitting: true, sourcemap: "external", publicPath: "/assets/", naming: { entry: "[dir]/[name].[ext]", chunk: "[name]-[hash].[ext]", asset: "assets/[name]-[hash].[ext]", }, define: { "process.env.NODE_ENV": JSON.stringify("production"), }, });
Building Multiple Outputs
// build.ts import { build } from "bun";
const builds = [ { entrypoints: ["./src/index.ts"], outdir: "./dist/esm", format: "esm" as const, target: "browser" as const, }, { entrypoints: ["./src/index.ts"], outdir: "./dist/cjs", format: "cjs" as const, target: "node" as const, }, { entrypoints: ["./src/index.ts"], outdir: "./dist/iife", format: "iife" as const, target: "browser" as const, }, ];
for (const config of builds) { await build({ ...config, minify: true, sourcemap: "external", }); }
console.log("All builds complete!");
Build Script with Watching
// watch-build.ts import { watch } from "fs"; import { build } from "bun";
async function buildApp() { console.log("Building..."); await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", target: "bun", }); console.log("Build complete!"); }
// Initial build await buildApp();
// Watch for changes
watch("./src", { recursive: true }, async (event, filename) => {
console.log(File changed: ${filename});
await buildApp();
});
Plugin System
Create custom build plugins:
import type { BunPlugin } from "bun";
const myPlugin: BunPlugin = {
name: "my-plugin",
setup(build) {
build.onLoad({ filter: /.custom$/ }, async (args) => {
const text = await Bun.file(args.path).text();
return {
contents: export default ${JSON.stringify(text)},
loader: "js",
};
});
},
};
await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", plugins: [myPlugin], });
Anti-Patterns
Don't Bundle Node Modules for Node Target
// Bad - Bundling all dependencies for Node await build({ entrypoints: ["./src/server.ts"], target: "node", // Missing external configuration });
// Good - Mark dependencies as external await build({ entrypoints: ["./src/server.ts"], target: "node", external: ["express", "mongoose", ""], // "" excludes all node_modules });
Don't Ignore Build Errors
// Bad - No error handling await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", });
// Good - Handle build errors try { const result = await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", });
if (!result.success) { console.error("Build failed"); process.exit(1); }
console.log("Build succeeded"); } catch (error) { console.error("Build error:", error); process.exit(1); }
Don't Minify Development Builds
// Bad - Always minifying await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", minify: true, // Hard to debug in development });
// Good - Conditional minification const isDev = Bun.env.NODE_ENV === "development";
await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", minify: !isDev, sourcemap: isDev ? "inline" : "external", });
Don't Over-Split Code
// Bad - Excessive code splitting await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", splitting: true, target: "bun", // Code splitting not needed for Bun target });
// Good - Split only when beneficial await build({ entrypoints: ["./src/index.ts"], outdir: "./dist", splitting: true, target: "browser", // Beneficial for browsers });
Related Skills
-
bun-runtime: Understanding Bun's runtime for target optimization
-
bun-package-manager: Managing build dependencies
-
bun-testing: Testing bundled code