Benchmarks Bundlers

Vite vs esbuild vs tsup

Cold production builds of a TypeScript library — ESM, minified, no declarations.

Products compared

Tests

Test 1 Time per pass

20 measured passes over the corpus. Box is the middle half of the runs, line is the median, whiskers reach the fastest and slowest pass, dots are every run. (LOWER ms = FASTER)

Time per pass (ms)
esbuild
Vite
tsup
All 20 samples as a table
RunesbuildVitetsup
116.8 ms163.6 ms203.4 ms
215.9 ms161.8 ms200.4 ms
315.7 ms169.1 ms203.8 ms
415.0 ms168.5 ms202.6 ms
516.5 ms171.9 ms203.2 ms
615.6 ms175.2 ms202.8 ms
716.4 ms170.7 ms203.0 ms
817.3 ms171.7 ms206.3 ms
915.9 ms170.8 ms205.3 ms
1016.7 ms184.9 ms204.5 ms
1115.6 ms175.8 ms204.2 ms
1216.2 ms172.7 ms202.7 ms
1315.4 ms171.8 ms203.8 ms
1417.1 ms169.3 ms206.7 ms
1516.2 ms173.6 ms203.4 ms
1616.5 ms169.9 ms202.9 ms
1715.3 ms167.9 ms202.9 ms
1815.5 ms167.8 ms204.1 ms
1914.9 ms169.7 ms205.3 ms
2014.7 ms170.1 ms204.2 ms
Full report, as hyperfine prints it

Benchmark 1: esbuild 0.28.2fastest

Time (mean ± σ)
16.0 ms ± 0.7 ms
Range (min … max)
14.7 ms17.3 ms
Median
15.9 ms 20 runs

Benchmark 2: Vite 8.2.2

Time (mean ± σ)
170.8 ms ± 4.7 ms
Range (min … max)
161.8 ms184.9 ms
Median
170.4 ms 20 runs

Benchmark 3: tsup 8.5.1

Time (mean ± σ)
203.8 ms ± 1.4 ms
Range (min … max)
200.4 ms206.7 ms
Median
203.6 ms 20 runs
Raw catalog JSON
Test conditions: rig, corpus, protocol
Rig
Machine
MacBook Pro
Chip
Apple M2 Max
Cores
12 CPU cores
Memory
96 GB
OS
macOS 26.6.2 (arm64)
Runtime
Node 24.19.0 (Vite, tsup); esbuild native binary; Bun 1.4.0 harness
Corpus
Name
zod 4.5.4 library source
Source
github.com/colinhacks/zod@v4.5.4/src
Files
124
Lines
36,620
Size
1.30 MB
Protocol
Warmups
3 unmeasured passes
Measured
20 passes per tool
Process
A new CLI process for every measured pass, output directory cleared between passes
Cache
Warm filesystem cache after 3 unmeasured passes per candidate
Output
Bundled output emitted to a dedicated directory per tool

What did we learn?

esbuild finished in 16 ms; Vite took 170 ms, tsup 204 ms. esbuild built zod in 15.9 ms at the median. Vite took 170.4 ms (10.7x slower); tsup took 203.6 ms (12.8x slower). esbuild and tsup produced byte-identical 426 KB bundles. Vite's output was 482 KB — the difference is almost entirely whitespace that Vite preserves in ES library builds for downstream tree-shaking.

What this does not prove

  • Cold builds only — no incremental state, fresh CLI process per pass, warm filesystem cache. No watch mode or hot module replacement timing.
  • One corpus: a zero-dependency TypeScript library (zod 4.5.4, 124 files, ~36,600 lines). Application builds with many dependencies, code-splitting, or CSS processing may produce different rankings.
  • Build speed says nothing about dev-server experience, plugin ecosystems, or output correctness beyond "it built."
  • All three tools use esbuild's minifier, but not identically. Vite delegates bundling to Rolldown (Rust), then runs esbuild for minification — but for ES-format library builds, Vite deliberately disables whitespace minification to preserve `/* @__PURE__ */` annotations for downstream tree-shaking. esbuild and tsup minify fully, including whitespace. Re-minifying Vite's output with `esbuild --minify-whitespace` alone brings it within 1.2% of esbuild's size.
  • Declaration file generation (.d.ts) is disabled for all candidates. tsup's `dts` option is off by default; enabling it invokes the TypeScript compiler and would add significant time.
  • Times are fresh-process wall clock, including runtime startup and CLI module loading. Measured floors on this rig: `node -e 0` ~24 ms, `vite --version` ~77 ms, `tsup --version` ~35 ms, `esbuild --version` ~6 ms (native binary). The tools' self-reported build timers exclude startup cost.
  • tsup is no longer actively maintained. Its README recommends tsdown as a successor. Results are included because tsup remains widely installed.

Rerun it yourself: the runner and this corpus definition are in the repository, and the methodology page covers what every run holds constant. Think a result is wrong? Open an issue with your rig and your samples.