Skip to content

esbuild: Fast JavaScript and TypeScript Bundling

DodaTech Updated 2026-06-22 7 min read

In this tutorial, you'll learn esbuild including bundling, Transpilation, Minification, plugins, and integrating with build scripts for extremely fast JavaScript and TypeScript builds.

Why esbuild Matters

Build speed has become a bottleneck in modern web development. Webpack, Rollup, and Parcel process each file through transformation pipelines that become slower as projects grow. esbuild rewrites the bundling process from the ground up in Go, achieving 10-100x speed improvements over JavaScript-based bundlers. This speed makes it ideal for development builds, CI pipelines, and as the foundation for tools like Vite.

By the end of this guide, you will bundle JavaScript and TypeScript with esbuild, configure plugins, and integrate it into your build pipeline.

What is esbuild?

esbuild is an extremely fast JavaScript bundler and minifier written in Go. It handles bundling, Tree Shaking, TypeScript stripping, JSX transformation, CSS bundling, and Minification.

flowchart LR
  A[Source Files] --> B[esbuild]
  B --> C[Lexing]
  C --> D[Parsing]
  D --> E[AST]
  E --> F[Transformation]
  F --> G[Code Generation]
  G --> H[Bundled Output]
  B --> I[Minification]
  B --> J[Source Maps]
  B --> K[Tree Shaking]

Installation

# npm
npm install --save-dev esbuild

# Or use the standalone binary via curl
curl -fsSL https://esbuild.github.io/dl/latest | sh

Verify

npx esbuild --version
# 0.24.0

Basic Usage

Command Line

# Bundle a single file
npx esbuild src/index.js --bundle --outfile=dist/bundle.js

# Bundle with minification
npx esbuild src/index.js --bundle --minify --outfile=dist/bundle.js

# Watch mode
npx esbuild src/index.js --bundle --watch --outfile=dist/bundle.js

# TypeScript
npx esbuild src/index.ts --bundle --outfile=dist/bundle.js

Expected Output

$ npx esbuild src/index.js --bundle --outfile=dist/bundle.js

  dist/bundle.js  12.5kb

⚡ Done in 8ms

API Usage

esbuild's JavaScript API is more flexible than the CLI.

const esbuild = require('esbuild')

// Simple build
esbuild.buildSync({
  entryPoints: ['src/index.js'],
  bundle: true,
  outfile: 'dist/bundle.js',
})

Async Build

async function build() {
  const result = await esbuild.build({
    entryPoints: ['src/index.js'],
    bundle: true,
    outfile: 'dist/bundle.js',
    minify: true,
    sourcemap: true,
    target: ['es2020'],
  })

  console.log('Build complete:', result)
}

build()

Watch Mode

async function watch() {
  const ctx = await esbuild.context({
    entryPoints: ['src/index.js'],
    bundle: true,
    outfile: 'dist/bundle.js',
  })

  await ctx.watch()
  console.log('Watching...')
}

watch()

TypeScript Support

esbuild handles TypeScript without configuration. It strips types and compiles to JavaScript.

// src/index.ts
interface User {
  name: string
  age: number
}

const user: User = { name: 'Alice', age: 30 }
console.log(user.name)
npx esbuild src/index.ts --bundle --outfile=dist/bundle.js

Expected Output

// dist/bundle.js
const user = { name: "Alice", age: 30 };
console.log(user.name);

Note: esbuild strips TypeScript types but does not perform Type Checking. Use tsc --noEmit separately for Type Checking.

TSConfig Paths

esbuild.buildSync({
  entryPoints: ['src/index.ts'],
  bundle: true,
  outfile: 'dist/bundle.js',
  alias: {
    '@': './src',
  },
})

JSX and React

const esbuild = require('esbuild')

esbuild.buildSync({
  entryPoints: ['src/app.jsx'],
  bundle: true,
  outfile: 'dist/app.js',
  loader: { '.jsx': 'jsx' },
  jsxFactory: 'React.createElement',
  jsxFragment: 'React.Fragment',
})

For React 17+ with the new JSX transform:

esbuild.buildSync({
  entryPoints: ['src/app.jsx'],
  bundle: true,
  outfile: 'dist/app.js',
  jsx: 'automatic',
  jsxImportSource: 'react',
})

Minification

esbuild.buildSync({
  entryPoints: ['src/index.js'],
  bundle: true,
  minify: true,
  outfile: 'dist/bundle.js',
})

Comparison

Build Size Time
Without minify 45 KB 12 ms
With minify 18 KB 18 ms
With minify + whitespace only 22 KB 14 ms

CSS Bundling

esbuild also bundles CSS:

esbuild.buildSync({
  entryPoints: ['src/styles.css'],
  bundle: true,
  outfile: 'dist/styles.css',
  loader: { '.png': 'dataurl' },
})

Plugins

esbuild has a plugin API for custom transforms and loaders.

Simple Plugin

const envPlugin = {
  name: 'env',
  setup(build) {
    // Intercept import paths called "env"
    build.onResolve({ filter: /^env$/ }, args => {
      return { path: args.path, namespace: 'env' }
    })

    // Load env variables
    build.onLoad({ filter: /.*/, namespace: 'env' }, () => {
      return {
        contents: JSON.stringify(process.env),
        loader: 'json',
      }
    })
  },
}

esbuild.buildSync({
  entryPoints: ['src/index.js'],
  bundle: true,
  outfile: 'dist/bundle.js',
  plugins: [envPlugin],
})

External Plugin

const externalPlugin = {
  name: 'external-react',
  setup(build) {
    build.onResolve({ filter: /^react$/ }, args => {
      return { path: args.path, external: true }
    })
  },
}

Integration with Build Scripts

Node.js Build Script

#!/usr/bin/env node
// scripts/build.js
const esbuild = require('esbuild')
const glob = require('glob')

async function build() {
  const entryPoints = glob.sync('src/**/*.ts').filter(f => !f.endsWith('.test.ts'))

  await esbuild.build({
    entryPoints,
    bundle: false,
    outdir: 'dist',
    format: 'esm',
    target: 'node18',
    platform: 'node',
    sourcemap: true,
  })

  console.log(`Built ${entryPoints.length} files`)
}

build().catch(() => process.exit(1))

Package.json Scripts

{
  "scripts": {
    "build": "node scripts/build.js",
    "build:prod": "node scripts/build.js --minify"
  }
}

Performance Benchmark

# esbuild
time npx esbuild src/index.js --bundle --minify --outfile=dist/bundle.js
# real    0m0.089s

# Webpack (for comparison)
time npx webpack --mode production
# real    0m2.450s

Common Errors

Problem Cause Fix
No loader configured for ".vue" files Vue files not handled esbuild does not support Vue SFCs natively; use a plugin or Vite
Cannot use import statement outside a module Not bundling ES modules Add --bundle flag
Type error: Property 'xyz' does not exist esbuild strips types but does not check them Run tsc --noEmit separately
Build failed with 1 error: Expected ";" Syntax error in source Check the line indicated in the error
Output file is empty Entry file exports nothing Ensure the entry file has side effects or a default export

Practice Questions

1. What language is esbuild written in?

Go.

2. How do you enable Minification in esbuild?

Use the --minify flag or minify: true in the API.

3. Does esbuild perform TypeScript Type Checking?

No. It strips types but does not check them.

4. What is the --bundle flag for?

It tells esbuild to resolve and bundle all imported dependencies into a single output file.

5. How do you watch for changes with esbuild?

Use --watch in the CLI or await ctx.watch() in the API.

Challenge

Create a Node.js script that uses esbuild's API to build a TypeScript library. The build should output both ESM and CommonJS formats, generate source maps, and minify the production build. Include an onResolve plugin that aliases a module path.

Real-World Task

Replace Webpack or another bundler with esbuild in a small to medium-sized project. Configure the build to handle JavaScript, TypeScript, CSS, and JSON files. Set up watch mode for development and production Minification. Measure the build time improvement. Run tsc --noEmit as a separate step for Type Checking.

Can esbuild replace Webpack completely?

For many projects, yes. esbuild handles bundling, Minification, and TypeScript. However, it lacks Webpack's plugin ecosystem and advanced features like HMR (though Vite, which uses esbuild, provides HMR).

Does esbuild support code splitting?

Yes. Use --splitting and --format=esm for Code Splitting. Each entry point and dynamic import generates a separate chunk.

Is esbuild production-ready?

Yes. Many large projects use esbuild in production. However, for complex web applications, consider using Vite (which uses esbuild under the hood) for a more feature-complete developer experience.

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro