{"id":13725356,"url":"https://github.com/Rugvip/ts-build-bench","last_synced_at":"2025-05-07T20:32:06.543Z","repository":{"id":42846023,"uuid":"262373848","full_name":"Rugvip/ts-build-bench","owner":"Rugvip","description":"Benchmarking different build setups for TypeScript web projects","archived":false,"fork":false,"pushed_at":"2023-10-19T18:05:18.000Z","size":505,"stargazers_count":12,"open_issues_count":23,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-10T14:22:26.578Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Rugvip.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2020-05-08T16:31:28.000Z","updated_at":"2022-08-09T14:37:54.000Z","dependencies_parsed_at":"2024-02-04T10:07:39.333Z","dependency_job_id":null,"html_url":"https://github.com/Rugvip/ts-build-bench","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rugvip%2Fts-build-bench","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rugvip%2Fts-build-bench/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rugvip%2Fts-build-bench/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rugvip%2Fts-build-bench/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Rugvip","download_url":"https://codeload.github.com/Rugvip/ts-build-bench/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224645341,"owners_count":17346128,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T01:02:20.413Z","updated_at":"2024-11-14T15:31:13.762Z","avatar_url":"https://github.com/Rugvip.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# ts-build-bench\n\nBenchmarking different build setups for TypeScript web projects\n\n## Conclusions (TL;RD of test logs)\n\nThe tests were carried out with a large https://github.com/spotify/backstage project in mind. That is, a monorepo with a large number of stand-alone packages that are depended on by a single package.\n\nVersions used for these tests were recent versions of Webpack 4, Typescript 3.9, Rollup 2, and Babel 7.\n\n### VSCode Performance\n\nThere's not much to do to improve performance here. Using a single package is roughly the same speed as using a monorepo. Pre-building packages in a monorepo and pointing `package.json` `types` to `dist/index.d.ts` can give you a performance boost of maybe 20-30%, but it's likely not worth the tradeoff of having to keep those up to date.\n\nJust point `types` to `src/` for development and if the project grows too big for VSCode, find other ways to split it.\n\n### Building \u0026 Bundling\n\nSeparate builds of each package is not worth the tradeoff of build complexity, as long as you're using one of the new ES20XX transpilers such as sucrase or esbuild. They are fast enough that the entire project can be compiled at once or served in watch mode. For building individual packages for publishing there's also a significant speedup, even though it might not make as much of a difference there.\n\nOut of esbuild and sucrase, esbuild is the faster one at the moment. It also produces code that is quicker to process by webpack, making it a better candidate for publish builds. It may however be worth using sucrase with webpack though, as it has react-hot-reload support, and the difference between them is pretty small.\n\nIt's also not worth generating type declarations as part of the build, or even type checking. It's faster to just let the build handle transpilation and bundling into js, and run tsc separately for type-checking and declaration file generation.\n\nHere are some rough numbers for a webpack build of a large project (100 packages, each with ~20 components/lib modules):\n\n```text\nts-loader:        70s\nsucrase-loader:   24s\nesbuild-loader:   21s\nbabel-loader:     86s\n```\n\nAnd for building a single one of those packages with different rollup plugins or tsc:\n\n```text\ntsc:                         11s\nrollup-plugin-typescript2:   22s\n@rollup/plugin-sucrase:      2.5s\nrollup-plugin-esbuild:       1.7s\n```\n\n### Type Checking\n\nWhen linting each package separately, using TypeScript project references provide a significant speedup for large projects. The initial build in a clean state is slightly faster than without project references, maybe 5-10%, as long as lerna is used, and not `tsc --build`. For incremental checks and watch mode project references become a must. Incremental checks can end up taking minutes otherwise, and there's really no global watch mode with lerna.\n\nThe above applies to if you want each package to have separate configuration though. The quickest way to do type checking, by an order of magnitude, is to have a single config file that points to all source code. This will however ignore any local tsconfig in the packages, and also require post-processing to move declarations files into `dist` folders before publishing. There doesn't seem to be an option to combine the speed of this approach with the change detection and convenience of project references.\n\nIn the end the single top-level config is likely the way to go, as a large project with project references can be prohibitively slow, taking many minutes to lint on the initial run, and tens of seconds to act on changes in watch mode.\n\nSome rough numbers for type-checking a project relatively large project (100 packages, each with ~20 components/lib modules):\n\n```text\nseparate tsc of each package:                            231s\nseparate tsc of each package, with project references:   225s\ntsc --build mode referencing all packages:               375s\nsingle top-level tsc pointing to all packages:           33s\nsingle top-level tsc incremental build:                  40s\n```\n\n## Project Layout\n\n- factory/ - Tools for creating projects of various size and configurations.\n- runner/ - Tools for running and benchmarking tasks inside said projects.\n- stats/ - Utils for presenting statistics from benchmark runs.\n- workdir/ - Directory where all benchmark projects are kept.\n\n## Usage\n\nNo real pattern here yet. Modify benchmarks and run them:\n\n```bash\n./benchmark-\u003cname\u003e\n```\n\nIf you give a number to benchmark, it will forward it as `count` to the benchmark function.\n\nPassing any of `inflate`, `prepare`, or `benchmark` will only run that part of the benchmark.\n\nFor example, running the benchmark park of the build benchmark with 5 iterations:\n\n```bash\n./benchmark-build benchmark 5\n```\n\nTo remove all projects in `workdir/`, run `./clean`.\n\n## Test logs\n\nThese are some written logs of different benchmarks run in this repo:\n\n- VSCode Performance: [test-log-vscode.md](./test-log-vscode.md)\n- Building and Bundling: [test-log-bundle.md](./test-log-bundle.md)\n- Type Checking with tsc: [test-log-typecheck.md](./test-log-typecheck.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRugvip%2Fts-build-bench","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRugvip%2Fts-build-bench","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRugvip%2Fts-build-bench/lists"}