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.
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.
"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: three.js x10 (ten copies of three.js, minified IIFE with source maps) and the excalidraw app (minified ESM). Only three.js x10 is drawn as bars: both bundlers produce the same exports from the same input. Without its persistent cache ts-r-build is slower than esbuild there. On excalidraw ts-r-build does less work than esbuild: it does not bundle template-literal import() yet, so it leaves out the 61 locale chunks esbuild emits (7.2 MB of output against 9.3 MB). Those runs, the single bundle and the 20 rebuilds, are in the table with that note, not drawn next to esbuild. Rolldown and Vite's production build have not been measured.
- ts-r
- Other tools
| What | ts-r-build | esbuild 0.28.2 | Notes |
|---|---|---|---|
| Bundle excalidraw, minified: no cache / persistent cache | 255 / 132 ms | 201 ms | Median of 10 runs. Not like-for-like: ts-r-build leaves out the 61 locale chunks esbuild emits (7.2 MB of output against 9.3 MB) |
| excalidraw: first build plus 20 edit-and-rebuild cycles, one process | 1,358 ms | 3,457 ms (context.rebuild) | Median of 5 runs. Not like-for-like: every build leaves out the 61 locale chunks |
| Peak memory, excalidraw, no cache / cached | 317 / 152 MB | 624 MB | Without the 61 locale chunks |
| Peak memory, three.js x10, no cache / cached | 459 / 275 MB | 695 MB | |
| three.js x10 output | 7.88 MB (+2.2%), same exports | 7.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.
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