esbuild Fast JS bundler

Version 0.28.2 · source

Start here

esbuild app.ts --bundle --outfile=out.js
Bundle to one file
esbuild app.ts --bundle --minify
Minified bundle to stdout
esbuild app.ts --bundle --outdir=dist
Write into a directory
esbuild app.ts --bundle --sourcemap
Emit a source map
esbuild app.ts --bundle --watch
Rebuild on change
esbuild app.ts --bundle --servedir=www
Dev server
esbuild app.ts --bundle --platform=node
Target Node
esbuild --version
Show version

Concepts

  1. Entry points app.ts, ...
  2. Module graph imports, packages
  3. Transformed TS/JSX to JS, minify
  4. Output --outfile / --outdir

Build

esbuild <entry> --bundle --outfile=<file>
Bundle one entry into a file
esbuild <a> <b> --bundle --outdir=<dir>
Bundle several entries into a directory
--minify
Minify whitespace, syntax and names
--sourcemap
Write a linked .map file
--sourcemap=inline
Embed the source map as a data URL
--sourcemap=external
Write the map without a comment link
--sources-content=false
Leave source text out of the map
--outbase=<dir>
Root for mirroring entry paths in outdir
--allow-overwrite
Let output replace an input file
--tsconfig=<file>
Use this tsconfig instead of discovery

Platform and format

--platform=browser|node|neutral
Pick target environment (default browser)
--format=iife|cjs|esm
Output module format
Bundled default: iife for browser, cjs for node, esm for neutral. Not bundling: input format is kept.
--target=es2020,chrome100
Lower syntax for these engines
Syntax only: esbuild does not polyfill APIs. Default is esnext.
--external:<pkg>
Leave a module out of the bundle
--packages=external
Keep every package import external
--splitting --format=esm --outdir=<dir>
Share code between entries in chunks
--global-name=<name>
Global variable name for iife output
--supported:<feature>=false
Force a syntax feature to be lowered
--chunk-names=<template>
Name split chunks, e.g. [name]-[hash]

Loaders and assets

--loader:.<ext>=<loader>
Choose how a file type is read
--loader:.png=dataurl
Inline images as data URLs
--loader:.png=file
Copy asset and import its path
--loader:.js=jsx
Allow JSX in .js files
--jsx=automatic
Use the React 17+ JSX runtime
--jsx-factory=<fn>
Function that JSX compiles to
--jsx-import-source=<pkg>
Package for the automatic JSX runtime
--asset-names=<template>
Name for copied file-loader assets
--entry-names=<template>
Output name pattern for entries
--public-path=<url>
Prefix for file-loader URLs
--out-extension:.js=.mjs
Use a different output extension
--inject:<file>
Prepend a file and replace globals from it
--banner:js=<text>
Add text at top of JS output
--footer:js=<text>
Add text at end of JS output

Optimize

--define:<name>=<value>
Replace an identifier with a constant
Value must be JSON or an identifier; strings need inner quotes: --define:ENV=\"prod\"
--define:process.env.NODE_ENV=\"production\"
Set NODE_ENV for dead-code removal
--drop:console
Remove console.* calls
--drop:debugger
Remove debugger statements
--drop-labels=<name>
Remove labeled statements
--pure:<fn>
Treat calls as side-effect free
--minify-whitespace
Minify only whitespace
--minify-syntax
Minify only syntax
--minify-identifiers
Minify only names
--keep-names
Keep function and class .name
--tree-shaking=true
Force tree shaking on, even unbundled
--legal-comments=<mode>
none, inline, eof, linked or external
--charset=utf8
Write non-ASCII characters unescaped
--mangle-props=<regex>
Rename matching properties
Unsafe: breaks dynamic access like obj[key].

Watch and serve

--watch
Rebuild when inputs change
Stops when stdin closes, so it exits in some CI or script setups.
--watch=forever
Keep watching after stdin closes
--watch-delay=<ms>
Wait before each rebuild
--servedir=<dir>
Serve a directory plus build output
--serve=<port>
Serve build output on a port
Default port is the first free one of 8000-8009. For development only.
--serve-fallback=<file>
Serve this page instead of a 404
--keyfile=<key> --certfile=<cert>
Serve over HTTPS
--cors-origin=<origin>
Allow cross-origin requests

Analyze and logs

--metafile=<file>
Write build metadata JSON
--analyze
Print a size report of the bundle
--analyze=verbose
Detailed report with import chains
--log-level=<level>
verbose|debug|info|warning|error|silent
--log-limit=<n>
Max messages shown (default 6, 0 = all)
--color=true|false
Force colored output
--abs-paths=code|log|metafile
Emit absolute instead of relative paths

Resolution

--alias:<from>=<to>
Rewrite an import path or package
Replacement resolves from the working directory.
--conditions=<names>
Extra package exports conditions
--main-fields=<fields>
Package.json fields to try, in order
--resolve-extensions=<list>
Implicit extensions, e.g. .ts,.js
--preserve-symlinks
Do not resolve symlinks

Transform stdin

esbuild --loader=ts < <in.ts>
Transform TypeScript from stdin
--sourcefile=<name>
File name for stdin errors and maps
--tsconfig-raw=<json>
Pass tsconfig contents inline
echo '<code>' | esbuild --minify
Minify a quick snippet

Recipes

Production browser bundle
esbuild src/index.ts --bundle --minify --sourcemap \  --target=es2020 --define:process.env.NODE_ENV=\"production\" \  --outfile=dist/app.js
Node CLI with dependencies external
esbuild src/cli.ts --bundle --platform=node --target=node20 \  --packages=external --format=esm --outfile=dist/cli.mjs
Dev loop with live static server
esbuild src/index.tsx --bundle --jsx=automatic --sourcemap \  --servedir=public --outdir=public/js --watch
Find what makes the bundle big
esbuild src/index.ts --bundle --minify --metafile=meta.json \  --outfile=/dev/null --analyze