ts-r-build

Bundler and minifier. Replaces esbuild, Rollup, Vite build.

  • Pre-alpha
  • Works from source

ts-r-build bundles and minifies TypeScript and JavaScript for production. Its command line follows esbuild 0.28.2, so most esbuild commands work after swapping the binary name. Like esbuild, it strips types without checking them.

First build plus 20 edit-and-rebuild cyclesShorter is faster. Pre-release build, real app.
  • ts-r-build269 ms
  • esbuild 0.28.2 (context.rebuild)1,294 ms

4.8× faster rebuilds

What switching looks like

Nothing is on npm yet. Once it is, switching looks like this: ts-r-build reads the config you already have, so the change is to the command, not the project.

package.json
  "scripts": {
-   "build": "esbuild src/app.ts --bundle --minify --outdir=dist",
+   "build": "ts-r-build src/app.ts --bundle --minify --outdir=dist",
  }

What works, and what doesn’t yet

Works today

  • Bundling ES modules and CommonJS, with tree shaking that honours sideEffects and /*#__PURE__*/
  • Output formats esm, cjs and iife, and code splitting with --splitting
  • Platforms browser, node and neutral; tsconfig paths and baseUrl
  • Minification of whitespace, identifiers and syntax
  • Source maps: linked, external, inline or both
  • JSX with the classic or the automatic runtime, --watch and a persistent build cache

Not yet

  • No plugins and no JavaScript config file or API
  • No CSS bundling; @import is not followed
  • No syntax lowering: targets below ES2022 are rejected
  • No --mangle-props, --drop, --pure or --keep-names
  • Minified output is about 3% larger than esbuild’s

Measured

Every run, on the same reference app as the home page, with the command and commit that recorded it.

ts-r-build against esbuild 0.28.2

Bundling private-app's web smoke entry (1,983 modules, minified, React's CommonJS build). Both bundles render the same HTML. ts-r-build's output is 2.7% larger than esbuild's. Rolldown and Vite's production build have not been measured.

Bundle the smoke entry, minifiedShorter is faster, in ms
  • ts-r
  • Other tools
  • ts-r-build, persistent cache55 ms
  • ts-r-build, no cache65 ms
  • esbuild 0.28.286 ms
First build plus 20 edit-and-rebuild cyclesShorter is faster, in ms
  • ts-r
  • Other tools
  • ts-r-build269 ms
  • esbuild 0.28.2 (context.rebuild)1,294 ms
Bundle size and the cargo xtask bench scenarios
Whatts-r-buildesbuild 0.28.2
Bundle size, minified320.9 kB312.4 kB (ts-r +2.7%)
Bundle size, unminified1,296.9 kB1,259.5 kB
cargo xtask bench build-cold (one process, no persistent cache)58.8 ms76.4 ms
esbuild's own bundler tests (oracle)643 of 746 compared cases pass (86.2%)reference

The design record was renumbered to 0008-bundler.md after this commit; the link points at the file as it was when the numbers were recorded.

How we measured
Measured
Wall time of whole processes, median of 10 runs for the smoke entry; cargo xtask bench for build-cold and build-incremental (ts-r's examples/build_loop.rs --edit against bench/js/esbuild-rebuild.mjs)
Machine
Apple M-series Mac, macOS arm64, release build (the exact chip was not recorded)
Software
ts-r-build release build with 4 threads; esbuild 0.28.2 pinned in bench/package.json
Input
private-app apps/web smoke-entry.tsx, which server-renders the shared layout components; the incremental run edits src/components/footer.tsx
Command
scripts/limit.sh --time-s 1200 -- node bench/private-app/run.mjs --src <private-app checkout>, then cargo xtask bench
Recorded in
commit 7db7af5

Correctness

Compared with the tool ts-r-build replaces, on its own tests and on real code.

  • Bundler86.1%

    643 of 746 compared cases pass (86.2%)

    esbuild 0.28.2's end-to-end bundler tests. Commit 7db7af5.

Command line

An excerpt of ts-r-build --help. You can also run it through the launcher as ts-r build.

Next to esbuild and Vite

Use ts-r-build where you call the esbuild command line today, or to build a library while the app keeps Vite. It has no JavaScript API yet, so scripts that call esbuild.build() from Node switch to the command line first. ts-r-dev uses the same bundler to pre-bundle an app’s dependencies.

ts-r-build --help
Usage: ts-r-build [options] [entry points]

  --bundle          Bundle all dependencies into the output files
  --format=...      Output format (iife | cjs | esm)
  --minify          Minify the output
  --outdir=...      The output directory
  --platform=...    Platform target (browser | node | neutral)
  --sourcemap       Emit a source map
  --splitting       Enable code splitting (requires --format=esm)
  --watch           Rebuild when a source file changes