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.
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.
"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.
- ts-r
- Other tools
- ts-r
- Other tools
| What | ts-r-build | esbuild 0.28.2 |
|---|---|---|
| Bundle size, minified | 320.9 kB | 312.4 kB (ts-r +2.7%) |
| Bundle size, unminified | 1,296.9 kB | 1,259.5 kB |
| cargo xtask bench build-cold (one process, no persistent cache) | 58.8 ms | 76.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.
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