ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 46

  1. Blog

esbuild-register vs jiti: 343ms vs 540ms Cold

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.

Aditya Challa·5 October 2026·4 min read

Hands-on
On this page
  1. What I tested
  2. Is esbuild-register faster on a cold start?
  3. Does jiti win once the cache is warm?
  4. Should you switch from esbuild-register to jiti?
  5. Sources
  6. Related

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.

What I tested

  • Machine: 8 vCPU Intel Xeon / 15 GB RAM Linux cloud box, Node 20.19.2, tested 5 Oct 2026 (about 23:54 to 00:00 IST). Shared box; each timed run spawned a fresh Node process.
  • Fixture: /workspace/bench-esbuild-jiti/. One entry.ts importing 20 mid modules and 40 util modules (61 .ts files). CommonJS package so node -r esbuild-register works without ESM loader flags.
  • Tools: esbuild-register 3.6.0 (esbuild 0.25.12) via node -r esbuild-register src/entry.ts; jiti 2.7.0 via node_modules/.bin/jiti src/entry.ts. Both printed the same result 970.
  • Timing: process wall clock via performance.now() around the child. Seven interleaved cold runs per tool with node_modules/.cache/jiti removed before every jiti cold sample. Seven warm pairs afterward without wiping the jiti cache.
  • Findings: cold medians esbuild-register 343 ms / jiti 540 ms (~1.57x). Warm medians jiti 185 ms / esbuild-register 350 ms (~1.9x the other way).
  • One surprise: jiti's first warm numbers looked "faster than physics" until I found the persistent cache folder. Without wiping it, you are not measuring cold transpile.
  • Not tested: ESM-only packages, TypeScript path aliases, tsx or ts-node, Bun, Windows/macOS, watch mode, or compiling to a dist folder with tsc.

Is esbuild-register faster on a cold start?

Metricesbuild-register 3.6.0jiti 2.7.0
Cold wall median (7 runs, jiti cache wiped)343 ms540 ms
Warm wall median (7 runs)350 ms185 ms
Modules loaded6161
Printed result970970

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.

Does jiti win once the cache is warm?

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.

Should you switch from esbuild-register to jiti?

SituationMy pick
One-shot script in CI / ephemeral containeresbuild-register
Local tool that reloads the same TS config oftenjiti
You already depend on jiti via Nuxt, c12, or similarStay on jiti
You only need a require hook and already ship esbuildesbuild-register is enough
You want a dedicated TS runner (tsx) instead of a register hookCompare 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.

Sources

  • https://www.npmjs.com/package/esbuild-register
  • https://github.com/egoist/esbuild-register
  • https://www.npmjs.com/package/jiti
  • https://github.com/unjs/jiti
  • https://esbuild.github.io/
  • https://nodejs.org/api/cli.html#-r---require-module

Related

  • https://www.shoppercove.com/blog/tsx-vs-ts-node
  • https://www.shoppercove.com/blog/swc-vs-esbuild-babel
  • https://www.shoppercove.com/blog/typescript-7-should-you-upgrade
  • https://www.shoppercove.com/blog/pnpm-vs-npm-vs-bun
  • https://www.shoppercove.com/blog/vitest-5-should-you-upgrade-october-2026
  • https://www.shoppercove.com/blog/jest-vs-vitest
  • https://www.shoppercove.com/blog/rolldown-vs-rollup
  • https://www.shoppercove.com/blog/vite-vs-parcel
typescriptbenchmarkingnode.jstranspilationperformanceci

Lab evidence

What I found running this

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.

Notes when a lab post goes up

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

Related links

  • Plate 94

    Should You Leave Prettier? 1.59s vs 0.51s

    dprint 0.60.1 vs Prettier 3.9.9 on 180 files (120 JS + 40 JSON + 20 MD, 38925 B pristine): write medians 514 ms vs 1586 ms; check 455 ms vs 1313 ms. Output 44805 vs 45285 B. All 120 JS files differed on arrow-param parentheses under these defaults.

    5 Oct 2026

  • Plate 69

    oxlint vs ESLint: Should You Switch? 9.8s vs 0.09s

    oxlint 1.87.0 vs ESLint 9.39.4 on react-hook-form (301 files): 0.09 s vs 9.81 s single-thread (6.02 s with --concurrency auto, 1.10 s warm --cache). @oxlint/migrate ported 42 of 84 rules natively, 80 with JS plugins. 315 vs 562 warnings; seeded test 11/15 native, 13/15 with JS plugins, ESLint 15/15.

    5 Oct 2026

  • Plate 80

    size-limit vs bundlesize: Should You Switch? 761ms vs 604ms

    size-limit 11.2.0 (@size-limit/file) vs bundlesize 1.0.0-beta.2 on 3 prebuilt dist JS files: brotli median 761 ms vs gzip 604 ms; size-limit gzip mode 621 ms. App reported 57.69 kB brotli / 62.20 kB gzip / 60.74 kB bundlesize gzip.

    5 Oct 2026

On this page

  1. What I tested
  2. Is esbuild-register faster on a cold start?
  3. Does jiti win once the cache is warm?
  4. Should you switch from esbuild-register to jiti?
  5. Sources
  6. Related
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove