ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 91

  1. Blog

tsup vs unbuild: Should You Switch? 931ms vs 2034ms

tsup 8.5.1 vs unbuild 3.6.1 on a 150-module TypeScript library (ESM+CJS): median 931 ms vs 2034 ms (~2.2x); with .d.ts 3213 ms vs 3740 ms (~1.16x). unbuild ESM 4.9% smaller, CJS 8.3% smaller; tsup README says not actively maintained.

Aditya Challa·5 October 2026·5 min read

Hands-on
On this page
  1. What I tested
  2. Is tsup faster than unbuild?
  3. Which one produces smaller output?
  4. Should you switch from tsup to unbuild?
  5. Sources
  6. Related

On a 150-file TypeScript library built to ESM plus CJS, tsup 8.5.1 took a median 931 ms and unbuild 3.6.1 took 2034 ms (~2.2x slower). With .d.ts generation on, the gap shrank to 3213 ms vs 3740 ms, and unbuild's ESM output was about 5% smaller (114.6 KB vs 120.5 KB).

Short answer: stay on tsup if raw build speed is your main concern and you are fine with a project whose README now says it is not actively maintained. Move to unbuild if you want an actively developed Rollup-based builder, smaller output, and --stub linking during development. No affiliate links in this post.

What I tested

  • Machine: 8 vCPU Intel Xeon / 15 GB RAM Linux cloud box, Node 20.19.2, tested 5 Oct 2026 (about 23:16 to 23:17 IST). Shared box; variants interleaved each round.
  • Fixture: 150 .ts modules plus one index.ts barrel. Each module has an interface, a union type, a string enum, a generic class, and a function that imports from the previous module (600 exports in total).
  • Tools: tsup 8.5.1 (esbuild 0.27.7) and unbuild 3.6.1 (rollup 4.64.0, rollup-plugin-dts 6.5.1), TypeScript 5.9.3. npm installed TS 5.9 rather than the 7.0 latest tag for these two builders. Both set to target: es2022, formats ESM and CJS, one entry.
  • Timing: one warmup each, then five interleaved rounds of four variants: tsup and unbuild, each with and without declaration output. Wall clock via process.hrtime around the full npx command.
  • Findings: no-dts medians 930.9 ms (tsup) vs 2033.9 ms (unbuild); with dts 3213.0 ms vs 3740.2 ms. Both outputs passed a smoke test: util149(1) returned 11176 from ESM and CJS, and both exposed 600 exports.
  • One surprise: unbuild exited with code 1 on the first run because of a "Potential missing package.json files" warning about my bare package.json. Setting failOnWarn: false (or adding a proper exports map) fixed it.
  • Not tested: tsdown, unbuild's mkdist bundleless mode, multi-entry libraries, watch mode, Vue or JSX sources, Windows/macOS.

Is tsup faster than unbuild?

VariantMedian wallRuns (ms)
tsup 8.5.1, ESM+CJS931 ms1027 / 890 / 931 / 1004 / 870
unbuild 3.6.1, ESM+CJS2034 ms2034 / 2099 / 1939 / 2054 / 1964
tsup 8.5.1, ESM+CJS + .d.ts3213 ms3448 / 3130 / 3162 / 3213 / 3234
unbuild 3.6.1, ESM+CJS + .d.ts3740 ms3817 / 3740 / 3570 / 3802 / 3707

Yes. tsup transpiles and bundles with esbuild, while unbuild runs Rollup with an esbuild transform, and on this fixture that Rollup path cost about 1.1 s more. Once declaration files are on, both spend most of their time in the TypeScript compiler, so the difference drops to about 0.5 s (~1.16x). For most libraries that publish types, that is the number that matters.

The bundler underneath is the real split. The Rolldown vs Rollup post and the SWC vs esbuild vs Babel post have engine-level numbers from the same box.

Which one produces smaller output?

Filetsup 8.5.1unbuild 3.6.1
ESM bundleindex.js 120,537 Bindex.mjs 114,578 B
CJS bundleindex.cjs 136,252 Bindex.cjs 124,942 B
Type declarationsindex.d.ts + index.d.cts, 106,671 B eachindex.d.ts + .d.mts + .d.cts, 105,187 B each
Total on disk470,131 B555,081 B

unbuild's JS was smaller: 4.9% for ESM and 8.3% for CJS. Most of the gap is tsup writing a // src/modN.ts comment before each module and emitting each class as var Svc0 = class with an extra prefix; field line, where Rollup kept plain class Svc0. unbuild's total is larger only because declaration mode compatible writes a third .d.ts copy. Neither output was minified; if you minify, see the Terser vs esbuild vs SWC minify post.

Should you switch from tsup to unbuild?

SituationMy pick
Single-entry library that ships types, builds in CIEither works; unbuild cost about 0.5 s more here
You rebuild constantly without types (local loops)tsup was 2.2x faster in this test
You want an actively developed tool for the next few yearsPlan a move: unbuild, or tsdown as the tsup README suggests
You link the package into an app during developmentunbuild, for unbuild --stub
Strict "no warnings" CI and no exports map yetFix package.json first or unbuild will fail the build

Bottom line: tsup won on speed (931 ms vs 2034 ms without types, 3.2 s vs 3.7 s with types) and unbuild won on output size and maintenance status. Who should not switch yet: teams on tsup with no build pain and no plan to touch their tooling this quarter. If you are also weighing TypeScript itself, read the TypeScript 7 upgrade post first, because declaration builds here still ran on TS 5.9.

How this was made: I generated the TypeScript fixture, ran the interleaved builds on the ShopperCove test box, and kept the timing and size JSON; the write-up was drafted with AI help and checked against that output.

Sources

  • https://github.com/egoist/tsup
  • https://tsup.egoist.dev/
  • https://github.com/unjs/unbuild
  • https://www.npmjs.com/package/tsup
  • https://www.npmjs.com/package/unbuild
  • https://tsdown.dev/guide/migrate-from-tsup

Related

  • https://www.shoppercove.com/blog/rolldown-vs-rollup
  • https://www.shoppercove.com/blog/swc-vs-esbuild-babel
  • https://www.shoppercove.com/blog/terser-vs-esbuild-swc-minify
  • https://www.shoppercove.com/blog/typescript-7-should-you-upgrade
  • https://www.shoppercove.com/blog/tsx-vs-ts-node
  • https://www.shoppercove.com/blog/rspack-vs-webpack
  • https://www.shoppercove.com/blog/turbo-vs-nx
  • https://www.shoppercove.com/blog/knip-vs-depcheck
tsupunbuildtypescriptbundlerbuild performancebundle sizeesmcjs

Lab evidence

What I found running this

Hands-on on ShopperCove box 5 Oct 2026 ~23:16-23:17 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 20.19.2). Fixture: 150 .ts modules + index.ts barrel (interface, union type, string enum, generic class, chained function each; 600 exports). Versions: tsup 8.5.1 (esbuild 0.27.7), unbuild 3.6.1 (rollup 4.64.0, rollup-plugin-dts 6.5.1), typescript 5.9.3; target es2022, ESM+CJS, single entry. 1 warmup each, 5 interleaved rounds. Medians: tsup no-dts 930.9 ms (1027.3/890/930.9/1003.7/870.2); unbuild no-dts 2033.9 ms (2033.9/2099.3/1939/2054.2/1964.2); tsup dts 3213 ms (3447.8/3130.3/3161.6/3213/3234.1); unbuild dts (compatible) 3740.2 ms (3817.4/3740.2/3570.4/3802.4/3707.1). Sizes: tsup index.js 120537, index.cjs 136252, d.ts/d.cts 106671 each; unbuild index.mjs 114578, index.cjs 124942, d.ts/d.mts/d.cts 105187 each. Smoke: util149(1)=11176 ESM+CJS both, 600 exports. Gotcha: unbuild failOnWarn exit 1 on missing package.json exports; set failOnWarn:false. Raw: /workspace/bench-tsup-unbuild/res-tsup-unbuild.json. Not tested: tsdown, mkdist mode, multi-entry, watch, Windows/macOS. No affiliate.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Related links

  • Plate 31

    Should You Leave Rollup? 964ms vs 246ms

    Rolldown 1.2.12 vs Rollup 4.64.0 on 501 ESM files (197380 B source): median wall 245.617 ms vs 964.3 ms (~3.9x). Output 130522 vs 126894 B. Direct node bin, 5 interleaved warm runs, no minify.

    5 Oct 2026

  • Plate 74

    Should You Leave Nx? 3378ms vs 1177ms

    Turbo 2.11.7 vs Nx 23.2.1 on 7 packages / 336 JS files: cold median 1177 ms vs 3378 ms (~2.9x). Warm both 7/7 local cache hits (Turbo wall ~138 ms / tool ~16 ms; Nx wall ~668 ms with daemon / tool ~31 ms).

    5 Oct 2026

  • Plate 99

    Rspack vs Webpack: Which Builds Faster? 0.54s vs 4.3s

    Rspack 2.2.8 vs Webpack 5.111.1 on a 201-module React fixture: cold production medians 0.54 s vs 4.33 s (~8.0x). Webpack+Babel vs Rspack+builtin:swc-loader. Raw bundles 174 KB vs 365 KB; gzip ~48 KB vs ~52 KB.

    5 Oct 2026

On this page

  1. What I tested
  2. Is tsup faster than unbuild?
  3. Which one produces smaller output?
  4. Should you switch from tsup to unbuild?
  5. Sources
  6. Related
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove