Use when bundling JavaScript/TypeScript code with Bun's fast bundler. Covers building for different targets, tree-shaking, code splitting, and optimization strategies.
Limited to specific tools
Additional assets for this skill
This skill is limited to using the following tools:
name: jutsu-bun:bun-bundler description: Use when bundling JavaScript/TypeScript code with Bun's fast bundler. Covers building for different targets, tree-shaking, code splitting, and optimization strategies. allowed-tools:
Use this skill when bundling JavaScript/TypeScript applications with Bun's built-in bundler, which provides exceptional performance and modern features.
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
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",
});
Bun supports multiple build targets:
bun - Optimized for Bun runtime (default)browser - Browser-compatible bundlenode - Node.js-compatible bundleControl output format:
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
format: "esm", // or "cjs", "iife"
});
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]",
},
});
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
Split code for better loading performance:
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
splitting: true, // Enable code splitting
target: "browser",
});
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"),
},
});
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",
});
Generate source maps for debugging:
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
sourcemap: "external", // or "inline", "none"
minify: true,
});
// 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!");
// 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"),
},
});
// 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!");
// 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();
});
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],
});
// 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
});
// 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);
}
// 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",
});
// 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
});