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.

excalidraw: first build plus 20 rebuildsShorter is faster. Pre-release build, real app.
  • ts-r-build1,358 ms
  • esbuild (context.rebuild)3,457 ms

2.5× 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 two public projects: the excalidraw app (minified ESM) and three.js x10 (ten copies of three.js, minified IIFE with source maps). Without its persistent cache ts-r-build is slower than esbuild on both. On excalidraw it also leaves out the 61 locale chunks esbuild emits, because it does not bundle template-literal import() yet (7.2 MB of output against 9.3 MB), which flatters its times. Rebuilds in one process are 2.5 times faster than esbuild's context.rebuild. Rolldown and Vite's production build have not been measured.

Bundle excalidraw, minifiedShorter is faster, in ms
  • ts-r
  • Other tools
  • ts-r-build, persistent cache132 ms
  • esbuild 0.28.2201 ms
  • ts-r-build, no cache255 ms
excalidraw: first build plus 20 rebuildsShorter is faster, in ms
  • ts-r
  • Other tools
  • ts-r-build1,358 ms
  • esbuild (context.rebuild)3,457 ms
Bundle three.js x10, minifiedShorter is faster, in ms
  • ts-r
  • Other tools
  • esbuild 0.28.2225 ms
  • ts-r-build, persistent cache241 ms
  • ts-r-build, no cache378 ms
Memory, output and the oracle
Whatts-r-buildesbuild 0.28.2
Peak memory, excalidraw, no cache / cached317 / 152 MB624 MB
Peak memory, three.js x10, no cache / cached459 / 275 MB695 MB
three.js x10 output7.88 MB (+2.2%), same exports7.71 MB
esbuild's own bundler tests (oracle)643 of 746 compared cases pass (86.2%)reference
How we measured
Measured
Wall time of whole processes with hyperfine (cargo xtask bench --repos), median; peak RSS of one extra run (--memory). Rebuilds: examples/build_loop.rs --edit against bench/js/esbuild-rebuild.mjs, editing excalidraw-app/components/AppWelcomeScreen.tsx
Machine
Apple M-series MacBook (macOS arm64, 16 cores, 48 GB), shared with other jobs while measuring; release build, 4 threads
Software
ts-r-build release build with 4 threads; esbuild 0.28.2 pinned in bench/package.json
Input
excalidraw (bench/dev/excalidraw/main.tsx, .woff2 as files, .scss empty) and three.js x10 at the commits pinned in bench/repos.toml
Command
cargo xtask bench --fetch-repos --repos excalidraw,three-x10 && cargo xtask bench --repos excalidraw,three-x10 --memory
Recorded in
commit 9c3a371

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