Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add project-reference-based webpack bundling #30

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mitchhentgesspotify
Copy link
Contributor

ts-project-references is similar to ts-transpile in that it uses webpack, ts-loader and typescript, except that it can reuse already-built typescript code.

Unfortunately, ts-loader and typescript don't allow using project references while also only transpiling at the same time. So, when bundling with ts-project-references, it's doing a full, slow type-checking compile.

However, its reuse of clean (unmodified), already-compiled sub-projects is slightly faster (per-sub-project) than having to transpile from scratch.

This means that in a sufficiently large composite project, making a change to a single sub-project and re-bundling is faster with ts-project-references than ts-transpile.
Additionally, as a side benefit, this reuse applies to the output from regular tsc --build runs, so "linting" the full repo also preps it for a faster bundle as well.

However, first time builds become far slower.

Here's some results from a single round of testing:

*** FIRST BUNDLE TIME ***
bundleTs                  | avg=39617ms stdev=0
bundleTsProjectReferences | avg=184977ms stdev=0
bundleSucrase             | avg=12786ms stdev=0
bundleEsbuild             | avg=10725ms stdev=0
bundleBabel               | avg=41364ms stdev=0

*** INCREMENTAL BUNDLE TIMES ***
bundleTs                  | avg=39513ms stdev=0
bundleTsProjectReferences | avg=32015ms stdev=0
bundleSucrase             | avg=13154ms stdev=0
bundleEsbuild             | avg=11397ms stdev=0
bundleBabel               | avg=40877ms stdev=0

`ts-project-references` is similar to `ts-transpile` in that it uses
`webpack`, `ts-loader` and `typescript`, except that it can reuse
already-built typescript code.

Unfortunately, `ts-loader` and `typescript` don't allow using project
references while also only transpiling at the same time. So, when
bundling with `ts-project-references`, it's doing a full, slow
type-checking compile.

However, its reuse of clean (unmodified), already-compiled sub-projects
is slightly faster (per-sub-project) than having to transpile from
scratch.

This means that in a sufficiently large composite project, making a
change to a single sub-project and re-bundling is _faster_ with
`ts-project-references` than `ts-transpile`.
Additionally, as a side benefit, this reuse applies to the output from
regular `tsc --build` runs, so "linting" the full repo also preps it for
a faster bundle as well.

_However_, first time builds become far slower.

Here's some results from a single round of testing:
```
*** FIRST BUNDLE TIME ***
bundleTs                  | avg=39617ms stdev=0
bundleTsProjectReferences | avg=184977ms stdev=0
bundleSucrase             | avg=12786ms stdev=0
bundleEsbuild             | avg=10725ms stdev=0
bundleBabel               | avg=41364ms stdev=0

*** INCREMENTAL BUNDLE TIMES ***
bundleTs                  | avg=39513ms stdev=0
bundleTsProjectReferences | avg=32015ms stdev=0
bundleSucrase             | avg=13154ms stdev=0
bundleEsbuild             | avg=11397ms stdev=0
bundleBabel               | avg=40877ms stdev=0
```
@mitchhentgesspotify
Copy link
Contributor Author

This PR depends on #28.

@mitchhentgesspotify
Copy link
Contributor Author

Weirdly, in the incremental bundle-ts-project-references, less than a second is spent compiling typescript code. So, ~30s is spent in webpack bundling. Next, I'll see how esbuild performs with Typescript Project References.

@mitchhentgesspotify
Copy link
Contributor Author

Next, I'll see how esbuild performs with Typescript Project References.

Hmm, since esbuild is transpiling typescript itself (it's not running tsc under-the-hood), it can't (and, doesn't really need) the performance benefits of project references, and therefore doesn't support it.

The way to "add" project-reference support to esbuild is with this plugin, but that's essentially just so the esbuild transpiler implementation can resolve the same file references that regular tsc can, it doesn't gain the same kind of "re-use the compiled output" benefits that tsc does - but, again, at its performance level it doesn't really need them either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant