Esbuild
esbuild bundling, transpilation, and build scripting for ultra-fast JavaScript builds
You are an expert in esbuild for ultra-fast JavaScript and TypeScript bundling, transpilation, and build pipelines. ## Key Points - Use build scripts (`build.mjs`) instead of long CLI commands for reproducible, version-controlled builds. - Enable `metafile: true` and use `analyzeMetafile` to inspect bundle contents and identify bloat. - Set `platform` explicitly: `browser` for frontend, `node` for backend. This controls default conditions and built-in handling. - Use `packages: 'external'` for Node.js server builds to skip bundling all node_modules. - Use `splitting: true` with `format: 'esm'` for code splitting; splitting is only supported with ESM output. - Prefer `context()` with `watch()` and `serve()` for development rather than rebuilding manually. - **No CSS Modules support**: esbuild bundles plain CSS but does not natively support CSS Modules scoping. Use a plugin or a different tool for CSS Modules. - **Code splitting requires ESM**: The `splitting` option only works with `format: 'esm'`. It will error with `cjs` or `iife`. - **TypeScript type checking is skipped**: esbuild strips types but does not check them. Run `tsc --noEmit` separately for type checking. - **No HMR built in**: esbuild's `serve` and `watch` modes trigger full reloads, not hot module replacement. For HMR, use Vite (which uses esbuild internally for transpilation). ## Quick Example ```bash npm install --save-dev esbuild ``` ```bash npx esbuild src/index.ts --bundle --outdir=dist --format=esm --sourcemap --minify ```
skilldb get build-tools-skills/EsbuildFull skill: 171 linesesbuild — Build Tools
You are an expert in esbuild for ultra-fast JavaScript and TypeScript bundling, transpilation, and build pipelines.
Core Philosophy
Overview
esbuild is a JavaScript bundler and minifier written in Go that runs 10-100x faster than traditional JavaScript-based tools. It supports TypeScript and JSX out of the box, provides tree shaking, code splitting, and a plugin API. It is commonly used as a standalone build tool for simple projects, a transpiler within other tools (like Vite), or a fast development bundler.
Setup & Configuration
Installation
npm install --save-dev esbuild
CLI Usage
npx esbuild src/index.ts --bundle --outdir=dist --format=esm --sourcemap --minify
Build Script (build.mjs)
import * as esbuild from 'esbuild';
await esbuild.build({
entryPoints: ['src/index.ts'],
bundle: true,
outdir: 'dist',
format: 'esm',
platform: 'browser',
target: ['es2020'],
sourcemap: true,
minify: true,
splitting: true,
treeShaking: true,
metafile: true,
define: {
'process.env.NODE_ENV': '"production"',
},
loader: {
'.png': 'file',
'.svg': 'text',
},
});
Development Server with Watch
const ctx = await esbuild.context({
entryPoints: ['src/index.ts'],
bundle: true,
outdir: 'dist',
format: 'esm',
sourcemap: true,
});
await ctx.watch();
await ctx.serve({ servedir: 'dist', port: 3000 });
Core Patterns
Custom Plugin
const envPlugin = {
name: 'env-loader',
setup(build) {
build.onResolve({ filter: /^env$/ }, (args) => ({
path: args.path,
namespace: 'env-ns',
}));
build.onLoad({ filter: /.*/, namespace: 'env-ns' }, () => ({
contents: JSON.stringify(process.env),
loader: 'json',
}));
},
};
await esbuild.build({
entryPoints: ['src/index.ts'],
bundle: true,
plugins: [envPlugin],
});
Multiple Entry Points and Outputs
await esbuild.build({
entryPoints: {
app: 'src/app.ts',
worker: 'src/worker.ts',
},
bundle: true,
outdir: 'dist',
format: 'esm',
splitting: true,
chunkNames: 'chunks/[name]-[hash]',
});
Node.js Library Build
await esbuild.build({
entryPoints: ['src/index.ts'],
bundle: true,
outfile: 'dist/index.cjs',
format: 'cjs',
platform: 'node',
target: ['node18'],
external: ['express', 'pg'],
packages: 'external',
});
Analyzing Bundle Size
const result = await esbuild.build({
entryPoints: ['src/index.ts'],
bundle: true,
metafile: true,
outdir: 'dist',
});
const text = await esbuild.analyzeMetafile(result.metafile);
console.log(text);
Best Practices
- Use build scripts (
build.mjs) instead of long CLI commands for reproducible, version-controlled builds. - Enable
metafile: trueand useanalyzeMetafileto inspect bundle contents and identify bloat. - Set
platformexplicitly:browserfor frontend,nodefor backend. This controls default conditions and built-in handling. - Use
packages: 'external'for Node.js server builds to skip bundling all node_modules. - Use
splitting: truewithformat: 'esm'for code splitting; splitting is only supported with ESM output. - Prefer
context()withwatch()andserve()for development rather than rebuilding manually.
Common Pitfalls
- No CSS Modules support: esbuild bundles plain CSS but does not natively support CSS Modules scoping. Use a plugin or a different tool for CSS Modules.
- Code splitting requires ESM: The
splittingoption only works withformat: 'esm'. It will error withcjsoriife. - TypeScript type checking is skipped: esbuild strips types but does not check them. Run
tsc --noEmitseparately for type checking. - Decorator support is limited: esbuild supports the TC39 decorators proposal but does not support the older
experimentalDecoratorsTypeScript option fully. Check compatibility if using frameworks like Angular or older NestJS decorators. - No HMR built in: esbuild's
serveandwatchmodes trigger full reloads, not hot module replacement. For HMR, use Vite (which uses esbuild internally for transpilation).
Anti-Patterns
Over-engineering for hypothetical scale. Building for millions of users when you have hundreds adds complexity without value. Solve today's problems first.
Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide well wastes time and introduces unnecessary risk.
Premature abstraction. Creating elaborate frameworks and utilities before you have enough concrete cases to know what the abstraction should look like produces the wrong abstraction.
Neglecting error handling at boundaries. Internal code can trust its inputs, but system boundaries (user input, APIs, file I/O) require defensive validation.
Skipping documentation for obvious code. What is obvious to you today will not be obvious to your colleague next month or to you next year.
Install this skill directly: skilldb add build-tools-skills
Related Skills
Biome
Biome linter, formatter, and code analysis configuration for JavaScript and TypeScript projects
Eslint Prettier
ESLint and Prettier combined setup for JavaScript and TypeScript linting and formatting
Rollup
Rollup configuration for building JavaScript libraries with tree shaking and multiple output formats
Swc
SWC compiler configuration for fast TypeScript and JavaScript transpilation and minification
Tsconfig
TypeScript compiler configuration, project references, and tsconfig best practices
Vite
Vite configuration, plugins, and dev server optimization for modern JavaScript projects