esbuild-register 3.6.0 vs jiti 2.7.0 on a 61-file TypeScript graph: cold wall medians 343 ms vs 540 ms (~1.57x); after jiti disk cache warm, 185 ms vs esbuild-register 350 ms. Same printed result 970.
4 min read
I timed esbuild-register 3.6.0 and jiti 2.7.0 on the same 61-file TypeScript graph: a cold run (jiti disk cache wiped) took a median 343 ms with esbuild-register and 540 ms with jiti. After jiti warmed its cache under node_modules/.cache/jiti, the same entry finished in 185 ms, while esbuild-register stayed near 350 ms.
Short answer: use esbuild-register for one-shot CI scripts and cold containers where nothing is cached. Prefer jiti when the same config or tool entry loads repeatedly on a developer machine. No affiliate links in this post.
| Metric | esbuild-register 3.6.0 | jiti 2.7.0 |
|---|---|---|
| Cold wall median (7 runs, jiti cache wiped) | 343 ms | 540 ms |
| Warm wall median (7 runs) | 350 ms | 185 ms |
| Modules loaded | 61 | 61 |
| Printed result | 970 | 970 |
On a wiped cache, yes. esbuild-register was about 1.6x faster for this graph. That is the number that matters for a fresh CI job or a container that never keeps node_modules/.cache.
For another "run TypeScript without a build step" angle on this site, see the tsx vs ts-node post. For compiler/minify speed after you do ship a build, see SWC vs esbuild vs Babel.
Yes on this fixture. After the first successful jiti run, median wall time dropped to 185 ms while esbuild-register stayed around 350 ms with no equivalent on-disk module cache in this setup. If your CLI or Nuxt-style config loader starts dozens of times a day on the same laptop, jiti's cache is the decision number.
Who should not lean on that cache: locked-down CI images that wipe the workspace every job, or teams that treat node_modules/.cache as disposable. In those cases the cold ranking returns.
| Situation | My pick |
|---|---|
| One-shot script in CI / ephemeral container | esbuild-register |
| Local tool that reloads the same TS config often | jiti |
| You already depend on jiti via Nuxt, c12, or similar | Stay on jiti |
| You only need a require hook and already ship esbuild | esbuild-register is enough |
| You want a dedicated TS runner (tsx) instead of a register hook | Compare tsx vs ts-node first |
Bottom line: 343 ms versus 540 ms cold is real, and so is 185 ms warm jiti. Pick based on whether your process keeps a cache. For ecosystem upgrade pressure around TypeScript itself, see TypeScript 7: Should You Upgrade?. Package installs around either hook are covered in pnpm vs npm vs Bun.
How this was made: I generated the 61-file fixture, installed esbuild-register and jiti on the ShopperCove test box, timed interleaved cold and warm runs while wiping jiti's cache for cold samples, and kept the JSON; the write-up was drafted with AI help and checked against that output.
Lab evidence
Hands-on on ShopperCove box 5 Oct 2026 ~23:54-00:00 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 20.19.2). Fixture: /workspace/bench-esbuild-jiti/ — 61 .ts modules (entry + 20 mid + 40 util), CommonJS. Tools: esbuild-register 3.6.0 (esbuild 0.25.12) via node -r; jiti 2.7.0 via local bin. 7 interleaved cold runs with node_modules/.cache/jiti wiped before each jiti sample: medians 343 ms vs 540 ms. 7 warm pairs without wipe: jiti 185 ms vs esbuild-register 350 ms. Output identical (970). Raw: /workspace/bench-esbuild-jiti/res-esbuild-jiti2.json. Not tested: ESM-only packages, path aliases, tsx/ts-node, Bun, Windows/macOS, watch mode, tsc emit. No affiliate.
bun test 1.4.2 vs Vitest 5.0.3 on 300 TypeScript tests in 60 files: warm wall medians 136 ms vs 1,673 ms (~12x); Vitest --no-isolate 765 ms (~5.6x). A 5-file vitest-API check (vi.fn, vi.mock, fake timers, spyOn, it.each, snapshot) passed 7/7 under Bun.
Hands-on6 Oct 20265 min read
Hands-on6 Oct 20269 min read
Hands-on6 Oct 20268 min read