esbuild

esbuild is a JavaScript and TypeScript bundler and minifier written in Go by Evan Wallace. Its headline feature is speed: it routinely bundles large projects 10–100 times faster than older JavaScript-based tools. That speed made it the engine inside many other tools — Vite uses it to pre-bundle dependencies and transform TypeScript in development, and tools like tsup, Bun's early builds, and countless CLIs rely on it.

You can use esbuild directly for libraries, Node services, serverless functions, and simple web apps, or indirectly through higher-level tools. Its design philosophy is to be fast and simple, and it intentionally leaves some features — notably type checking — to other tools.

TL;DR

Quick Example

Bundle a TypeScript React app for the browser, with minification and source maps:

Bundle a Node.js Lambda handler into a single file, leaving the AWS SDK external:

metafile: true produces a JSON report of what ended up in the bundle — feed it to the esbuild bundle analyzer to find heavy dependencies.

Core Concepts

Why esbuild Is Fast

Build vs Transform

Loaders

Loaders tell esbuild how to interpret a file type: js, ts, jsx, tsx, css, json, text, base64, dataurl, file, copy, and empty. For example, --loader:.png=file copies images to the output directory and returns their URL.

Platforms, Formats, and Targets

esbuild lowers modern syntax to older targets where it can, but it doesn't add polyfills for missing runtime APIs.

Plugins

Plugins hook into resolution (onResolve) and loading (onLoad). Common uses: aliasing paths, loading files from virtual modules, compiling Svelte or Vue files, and integrating environment-specific imports.

Watch and Serve

context() returns a build context with watch() for incremental rebuilds and serve() for a simple development server. Incremental rebuilds reuse parsed files and are often a few milliseconds.

What esbuild Leaves Out

Best Practices

Pair It With a Type Checker

Run tsc --noEmit in CI and your editor. esbuild compiling successfully doesn't mean your types are correct.

Set target Explicitly

Match your supported browsers or Node version so esbuild lowers exactly what's needed and no more.

Mark Runtime-Provided Packages External

For Node and serverless bundles, externalize packages the runtime already provides or native modules that can't be bundled.

Analyze Bundles With the Metafile

Use metafile output and the analyzer to catch accidental imports of large libraries.

Use It Through Higher-Level Tools for Apps

For full applications with routing, HMR, and asset pipelines, Vite gives you esbuild's speed with a complete developer experience.

Common Mistakes

Expecting Type Errors to Fail the Build

esbuild strips types without checking them. A build can succeed with serious type errors unless tsc runs separately.

Bundling Native Node Modules

Packages with .node binaries can't be bundled. Mark them external and ship them in node_modules.

Assuming Polyfills Are Added

Lowering syntax doesn't add missing APIs like Array.prototype.at for old browsers. Add polyfills explicitly if you target old environments.

Relying on isolatedModules-Incompatible Code

esbuild compiles each file independently. Re-exporting types without export type or using const enum across files can break. Enable isolatedModules in tsconfig.json to catch this.

Comparison

FAQ

What is esbuild used for?

esbuild bundles and minifies JavaScript and TypeScript for browsers and Node.js. It's used directly for libraries, CLIs, and serverless functions, and indirectly inside tools like Vite.

Why is esbuild so fast?

It's compiled Go code that uses parallelism across CPU cores and processes source in very few passes, avoiding much of the overhead of JavaScript-based bundlers.

Does esbuild type-check TypeScript?

No. It removes type annotations and compiles to JavaScript. Run the TypeScript compiler with --noEmit to check types.

Should I use esbuild or Vite?

For a web application, use Vite — it uses esbuild internally and adds a dev server, HMR, and optimized production builds. Use esbuild directly for libraries, Node services, or custom build scripts where you want minimal tooling.

Related Topics

References