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

Multiples re-compile when using webpack-dev-server with project references #1157

Closed
noelebrun opened this issue Jul 19, 2020 · 30 comments
Closed
Labels

Comments

@noelebrun
Copy link

Expected Behaviour

Build referenced projects, and then run a single Webpack compilation.

Actual Behaviour

Multiples Webpack compilations are ran, my guess is that it watch referenced project and re-compile for each emitted file by the referenced project instead of waiting for the referenced project to be compiled first.

Steps to Reproduce the Problem

  • Clone this sample repo using project references: monorepo-typescript-references
  • Run yarn at the root
  • Move current directory to /packages/app
  • Run yarn webpack-dev-server
  • Output is:
ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from /Users/noelebrun/Documents/projects/monorepo-webpack/packages/app
ℹ 「wdm」: Compiled successfully.
ℹ 「wdm」: Compiling...
ℹ 「wdm」: Compiled successfully.
ℹ 「wdm」: Compiling...
ℹ 「wdm」: Compiled successfully.
ℹ 「wdm」: Compiling...
ℹ 「wdm」: Compiled successfully.
  • Edit /packages/utils/src/index.ts
  • Additional output is:
ℹ 「wdm」: Compiling...
ℹ 「wdm」: Compiled successfully.
ℹ 「wdm」: Compiling...
ℹ 「wdm」: Compiled successfully.

Location of a Minimal Repository that Demonstrates the Issue.

Linked above: monorepo-typescript-references

Additional notes

As you can see from the steps to reproduce, when running webpack-dev-server for the first time, 4 compilations are ran. My first guess is that it's due to the packages/utils project to output 4 files when built (index.js, index.d.ts, index.d.ts.map, index.js.map): the watcher would trigger 4 separate compilations for each of those files.

When editing the file in the referenced project, two compilations are triggered (maybe because the .d.ts and the .d.ts.map are not re-build when not changing types so only 2 files are updated in the build folder?).

Note that, when running webpack-dev-server a second time when the referenced project is already built, only one compilation occurs.

@johnnyreilly
Copy link
Member

This may be intended behaviour - but I'm not certain. The idea being that in watch mode all the projects that are in scope may need to be rebuilt to ensure a complete build. I'm not clear how "smart" we are in terms of knowing when recompilation is unnecessary.

@sheetalkamat / @andrewbranch can you comment?

@andrewbranch
Copy link
Contributor

Unfortunately I don’t know enough about how webpack-dev-server works to know why this is happening and how easy it is to avoid it. My first question would be whether the same happens with webpack --watch.

@sheetalkamat
Copy link
Contributor

sheetalkamat commented Jul 24, 2020

I dont know enough about dev server either but i was trying to clone and repro and i get error:

c:\temp\monorepo-typescript-references>yarn
internal/modules/cjs/loader.js:796
    throw err;
    ^

Error: Cannot find module 'c:\Users\noelebrun\Documents\projects\monorepo-webpack\.yarn\releases\yarn-berry.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:793:17)
    at Function.Module._load (internal/modules/cjs/loader.js:686:27)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1043:10)
    at internal/main/run_main_module.js:17:11 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

c:\temp\monorepo-typescript-references>

Note i will be out of office next week and might be busy catching with our 4.0 stuff week afterwards so will be some time before i take a look and comment on this one

@noelebrun
Copy link
Author

noelebrun commented Jul 24, 2020

Sorry for the absolute path in the Yarn config, it just fixed it.

Regarding webpack --watch, I tried it and it seems to have a different behavior. The first compilation is only run once, same thing when saving a file in the Webpack project (app workspace in the example monorepo). But when saving a file in another workspace of the monorepo, it does compile twice.

I'm not sure how much webpack --watch and webpack-dev-server are different in terms of detecting changes and triggering new compilation. I will try to take a closer look at it.

@appzuka
Copy link
Member

appzuka commented Jul 27, 2020

I have loaded the repo and can confirm the multiple recompiles. Tracing the webpack watch code I understand why it is happening although I'm not sure there is a simple fix.

After utils/src/index.ts is changed the following steps occur:

  1. watch starts
  2. webpack starts first compile
  3. webpack calls ts-loader
  4. ts-loader builds project references, generating utils/build/*.js files
  5. ts-loader builds ts files from main app
  6. webpack bundles all files and generates output
  7. watch starts again

At step 7, any files which have been changed since step 2 (although see note below) will trigger a re-compile. Because the utils/build/*.js files were created after step 2, a new build will be triggered.

The re-build does not cause the project references to be rebuilt because the utils/src/*ts files have not changed. Therefore no new files are created in utils/build and the build cycle ends after the second build.

The second build is not necessary because ts-loader caused the project reference to be built at the start of the build process. By the time webpack included those files the new versions were already on disk. Webpack does not know this and assumed that since the files changed after the compilation was started that another compilation may be needed.

A sidenote is that it is not quite true that files changed since step 2 will cause a recompile. Watchpack measures the accuracy of the filesystem and adds that figure to the modified time of the file to ensure that changes will cause a recompile. Watchpack initially sets this at 1000ms:

https://github.com/webpack/watchpack/blob/7cb31caedeb4d258e6214f6f8c64ef9e3d53b44a/lib/DirectoryWatcher.js#L13

But after a file is changed it is reduced.

https://github.com/webpack/watchpack/blob/7cb31caedeb4d258e6214f6f8c64ef9e3d53b44a/lib/DirectoryWatcher.js#L757

On my system under WSL this is 100ms but it could be 10ms under Windows. The FS_ACCURACY is not reduced from 1000ms until the first file is changed, so webpack will recompile until 1000ms after the start of the compilation. This is the cause of even more compiles on the first cycle. This could be fixed by a change to watchpack, but the double compile would remain.

I'm not sure there is a simple solution to this. The guidelines for writing a webpack loader include:

  • Keep them simple
  • Make them stateless
  • Utilise chaining

Including projectReferences into ts-loader breaks these guidelines. ts-loader reads files directly from disk and writes files directly to disk. I could argue that ts-loader is not a normal loader. ProjectReferences are a great capability so perhaps it is worth breaking the guidelines. The second compile seems a small price to pay as it is very fast anyway.

I do wonder it if would have been better to keep ts-loader simpler and benefit from the new features added to tsc (project references & watch api) by a separate mechanism, perhaps a plugin or a package such as lerna.

@johnnyreilly
Copy link
Member

Awesome write up @appzuka!

I do wonder it if would have been better to keep ts-loader simpler and benefit from the new features added to tsc (project references & watch api) by a separate mechanism, perhaps a plugin or a package such as lerna.

It's arguable that ts-loader has 2 modes:

  1. transpileOnly: true - this is "simple" in terms of what ts-loader does; just file by file compilation. Fast but you don't get much; no type checking etc. Simple ts-loader requires pairing with fork-ts-checker-webpack-plugin to get the extra goodness
  2. transpileOnly: false - the not simple but "batteries included" version of ts-loader. From the users experience it's entirely plug and play.

I typically use 1. from the above for my own use cases. Another thing to consider is project references. It potentially makes use case 2. more scalable; speed even as your codebase grows by splitting up your codebase into multiple projects.

Side note: since v5 fork-ts-checker-webpack-plugin has also offered project references support (I haven't tested it out though)

@desmap
Copy link

desmap commented Aug 24, 2020

@appzuka @johnnyreilly thanks for the amazing write-ups. After checking gazillions of ways to do monorepos, I find TS' project references the way to go and thus a must-have for my use cases. So I need project references in any way, the question is now how and I am wondering which of the following is the better option:

1. Compilation done by tsc -b -w only; webpack and webpack-dev-server only bundle already compiled js files and only frontend code
2. webpack + ts-loader for frontend code

My gut feeling (but pls correct me): 2 has more optimization options (ts-fork-checker, parallelized builds, etc.) but it's not clear for me ATM if project references are properly implemented with ts-loader, things such as double compilation would be just the tip of the iceberg, I assume there are more difficulties/inconsistencies when I just look at the issues on that front. Also that I've two different compilations (tsc for backend code and webpack + ts-loader for frontend code) creates a complexity/mental overhead in the build system, so IDK.

I'd think that 1 even with just one compilation must be slower because of lacking optimization options, but I'd would have proper/solid project reference support. A clean build system which I could ELI5: tsc compiles, webpack bundles. And maybe it's not so slow because of incremental builds, so yeah.

I tend to go for 1 but maybe I missed something and hence would love to hear your thoughts before I enter the rabbit hole of trying and benchmarking both 1 and 2.

@desmap
Copy link

desmap commented Aug 25, 2020

So, I tested option 1 (tsc transpiles, webpack bundles) with a mini hello world repo, so I can't say anything about speed. The setup was easy, it feels quite responsive but you have also double bundlings from webpack if you change a reference. Once you set an aggregateTimeout of minimum 750 in this mini-repo you can avoid these double compiles (which is not really solution). So you face those multi compiles also with option 1 BUT just the webpack bundling is multiplied not the tsc transpilation step. I assume that latter takes more time than a pure webpack bundling, so even if we dropped the aggregateTimeout the double bundling should not hurt us so much like full multiple compilation incl transpilation. Does this make sense?

I am still curious to try option 2. This would mean I take the with webpack + ts-loader compiled folder out of the TS solution file's path, so tsc doesn't compile that folder anymore, right? I'd get fork-checker and thread-loader. However, IDK how much latter will speed up everything.

Edit: besides this performance topic; could you share your experience with ts-loader and fork-checker in the context of project references? Is is solid or not? Cmon guys, don't be so shy.
Edit2: one drawback I just realized, I can't just run tsc without type-checking which I could with ts-loader.
Edit3/note to myself: fork-ts-checker has perf issues with project refs TypeStrong/fork-ts-checker-webpack-plugin#463
Edit4: just learned that project refs cant have transpileOnly true, see #1158 so disabling type checking is with neither option possible; considering that forked type checking with fork-ts-checker has perf issues, see Edit 3, there is no point in trying option 2; the only thing i could add are thread-loader or happypack to boost the bundlings if it ever gets a problem, this would also solve perf issues due to multiple compilations because i shouldn't get more multiple compilations than cpu threads.

@johnnyreilly
Copy link
Member

Hey @desmap ,

Thanks for posting this feedback - it's hugely helpful! The project references support in ts-loader is fairly mature now thanks to the stellar efforts of @andrewbranch and @sheetalkamat 🌻❤️

One thing that we've never quite done is good documentation around how to use project references with ts-loader. What workflows are possible, what aren't. What's good practice. What doesn't work etc.

If you were tempted to provide a docs PR to add your findings to ts-loaders README we'd surely appreciate it!

PS I'm on my holidays so my replies may be sporadic

PPS incidentally the fork-ts-checker-webpack-plugin with transpileOnly setup may be interesting to @piotr-oles who added project references support to fork-ts-checker-webpack-plugin. Perhaps you are not using it in the manner he intended?

@desmap
Copy link

desmap commented Aug 25, 2020

to provide a docs PR

I'd love to but ATM it would be just kind of a 'stay away' from ts-loader if you need project references. IDK if such a sentence or a comparison table where ts-loader is dark red is in your interest. ;)

To be fair, I just tried ts-loader with a perfectly working project references project (option 1) and still, after a lot tweaking, ts-loader couldn't import a project reference, e.g. a file containing import reference from '../reference'. Interestingly it recompiled on change of that references, so not that bad but it means also that it found that reference. Strange and hints to deeper issues. Look, I spent now 120min, tried a lot re folders, context, configs here and there.

I'd like to love ts-loader but this and people reporting a lot of issues here and severe issues on the fork-checker side makes using ts-loader a big ask.

But here your comparison table in the context of project references:

webpack+ts-loader tsc+webpack
transpileOnly only in not referenced files no
paralllel TS transpilations only in not referenced files no
parallel webpack bundling yes yes
fork-ts-checker not sure[3] no
one less dependency no yes
100% project ref compatibility, now and in future no yes
no multi bundlings yes no

[3] couldn't get it to work and ts-fork-checker has severe perf issues with project references reported by multiple people TypeStrong/fork-ts-checker-webpack-plugin#463 and TypeStrong/fork-ts-checker-webpack-plugin#453*

Perhaps you are not using it in the manner [fork-ts-checker maintainer] intended?

Did you check both issues above? Once you did there is no need to try fork-ts-checker anymore and again: ts-loader has to check anyway b/c of [1]

Man, I am sorry and even if you found the bug why it doesn't find my references (or maybe I just didn't get it), tell me why should I use ts-loader with project references? Maybe I still missed something and that's the reason why I am here. Your feedback on the comparison table is welcome.

@johnnyreilly
Copy link
Member

Hey @desmap,

I'm sorry to hear project references support in ts-loader and fork-ts-checker-webpack-plugin isn't covering your use case.

@desmap
Copy link

desmap commented Aug 25, 2020

covering your use case

You mean using "project references"? Yes, that's my use case which your README states as a feature of ts-loader. Hope that use case is not too exotic.

Is there a reason you do not provide a working example with ts-loader and project references in the repo? This would be a good start and highly appreciated by all users (also as a signal that ts-loader really supports project references). However, that's your call.

@appzuka
Copy link
Member

appzuka commented Aug 25, 2020

Hi @desmap,

I have been spending a lot of time looking at project references and ts-loader recently. I agree that some documentation and examples are desperately needed and it is my intention to write some once I feel I understand the subject enough.

I have a project using multiple project references, ts-loader, transpileOnly and fork-ts-checker-webpack-plugin. It works well and the performance seems good but there are a lot of options in tsconfig, webpack.config and ts-loader to get right and also you need to set up the project structure just right to get all the resolutions working (I use yarn workspaces). When I am done I will write this all up and provide an example project. In the meantime, if you have a repo to share with me that shows your issues I would be happy to take a look.

@desmap
Copy link

desmap commented Aug 25, 2020

hey @appzuka, thanks for the prompt/kind/empathetic reply, this was already quite helpful to move fwd.

to get all the resolutions working (I use yarn workspaces).

I think this is the problem. Of course, I could use yarn workspaces to import packages within a monorepo yarn-workspaces-style but this is not needed with project references which makes things easier. Not that yarn workspaces is bad but it has its own warts.

My feeling is that ts-loader deviates here from the official project references spec, can't resolve package out of the scope[1] and thus needs a solution to resolve those. So instead of just import reference from '../reference', you need to declare "reference": "workspace:*" in package.json (in case you use yarn or pnpm workspaces) and then you can do import reference from 'reference'.

Is it a big deal? IDK, for some maybe, for some not. If this is really the case (I am too tired now to test this), I could make a PR for the README stating that resolving doesn't match the official specs and you still need kind of dedicated resolving solution such as a yarn workspaces or maybe even tsconfig paths (but again we now have project references and all this extra stuff shouldn't be required).

[1] out of the scope of the current reference folder with its own tsconfig.json (not the solutions tsconf)

@appzuka
Copy link
Member

appzuka commented Aug 25, 2020

In my project, yarn workspaces automatically creates a link to the referenced project in node_modules:

node_modules/reference -> ./workspace/reference

In the project reference directory I include a package.json which contains a "main" field which points to the transpiled code in workspace/reference/lib.

Then, you can just import the reference from your main project:

import { reference } from 'reference'

The module resolution for both tsc and webpack correctly resolves this to the transpiled code via the symbolic link in node_modules. (Assuming you are using the 'node' module resolution strategy in tsconfig.json.) You need to make sure you are resolving to the transpiled js code, not the source ts code in the project reference, otherwise typescript complains that files are outside the root dir of the main project.

You could do this without yarn workspaces. You could just create the links in node_modules yourself. Or you could do without the link and include a link to the reference in "paths" within tsconfig.json and also the resolve/modules setting in webpack config. I am not using yarn workspaces to build the referenced project, just to manage the link in node_modules.

I hope this helps.

@desmap
Copy link

desmap commented Aug 25, 2020

Thanks again for the quick feedback. I found the reason: ts-loader CAN resolve project references without any extras, I needed to add resolve: { extensions: ... } which is usually not needed, whatever.

FWIW, I didn't experience double compiles, so changing the comparison above.

FWIW2, I tested compile times with transpileOnly: true, no change to false. So now, I wonder what would fork-ts-checker help if ts-loader checks anyway (same topic I brought up earlier).

@desmap
Copy link

desmap commented Aug 25, 2020

FWIW3, tested also fork-ts-checker: there's no perf difference to before or before and transpileOnly: false. But at least it's not dramatically slower like people reported.

FWIW4, I tested also compilation with transpileOnly: true without fork-ts-checker and as expected full checks with deliberate errors.

So, same speed, two more dependencies but just one compile step. much better impression but still no clear advantage over option 1 but maybe I have to look further, I am continuing tmr, let's see

@appzuka
Copy link
Member

appzuka commented Aug 25, 2020

I believe transpileOnly: true only affects code in the main projects, not the referenced projects. The project references will be compiled as normal. If the majority of your code is in the project references you will not see a speed improvement with transpileOnly: true.

If you are not using transpileOnly: true my understanding is that there is no benefit to using fork-ts-checker.

In my project I only experience the double compiles in watch mode when I change one of the source files in a project reference. If I change a source file in the main projects I do not see a double compile. This behaviour is understandable.

@desmap
Copy link

desmap commented Aug 25, 2020

can confirm, it's super fast in the not referenced files (updating table).

I couldn't get fork-ts-checker to work but I'll check tmr.

However, the now working transpileOnly on main files might be a very good reason to go for ts-loader, @appzuka thanks for you support

@johnnyreilly let me tinker around a bit more and I might PR an updated version of the comparison table, I mean now it looks way better than few hours before

Edit: note to myself, I still need to test happypack and/or threaded-loader

@desmap
Copy link

desmap commented Aug 25, 2020

I couldn't get fork-ts-checker to work

I think I needed to remove transpileOnly: true from ts-loader's options because it seems to affect fork-ts-checker as well. If it's false ts-loader doesn't type check in case fork-ts-checker is activated as a plugin, right?

@desmap
Copy link

desmap commented Aug 25, 2020

this is nuts. I have the feeling the perf is very much dependent if you do changes in non-referenced files vs referenced files (it's exactly the same with option 1). Latter make the biggest impact. The rest (transpilesOnly, fork-ts) doesn't make that much of an impact, i barely notice anything... strange

@desmap
Copy link

desmap commented Aug 26, 2020

fyi, 4-core vps[3] benchmarks, reference and non-reference files have each 1,000 functions

tl;dr: option 1 is faster on reference builds and warm starts, option 2 on non-reference builds and cold starts

setup type-checking? initial build w/o changes before (warm start) initial build w/ changes before initial build after rm -r dist (cold start) rebuild on 1st change in non-reference rebuild on 1st change in reference rebuild on 2nd change in non-reference rebuild on 2nd change in reference
OPTION 1 tsc -b -w + webpack-dev-server just bundling tsc's output, aggregateTimeout: 0 1.5s 13s 14.7s[2] 2.3s 3.4s 2.2s 2.4s
OPTION 2 webpack-dev-server+tsloader, fork-ts-checker 5.4s 5.2s 9.6s 1.8s 4.5s 1.1s 3.3s
webpack-dev-server+tsloader - - 9.5s 2.1s 4.2s 1.9s 4.4s
webpack-dev-server+tsloader, transpileOnly - - 8s 1s 4.4s 0.4s 3.7s
webpack-dev-server+tsloader, transpileOnly, fork-ts-checker - - 8.1s 0.9s 4s 0.7 4s
just tsc -b -w without bundling 0s 11.5s 13.2 1.9s 2.9s 1.67s 1.94s
just webpack-dev-server bundling tsc's output, aggregateTimeout: 750 - - 1.56s 0.5s 0.6s 0.4s 0.3s
just webpack-dev-server bundling tsc's output, aggregateTimeout: 0 - - 1.5s 0.4s 0.5s 0.5s 0.4s
webpack-dev-server+tsloader w/ happyPackMode, fork-ts-checker w/semantic+syntatic, threadloader w/infinite pool -[1] - - - - - -

[1] Couldn't get thread-loader to work, got Cannot read property 'options' of undefined
[2] Be aware that it needs a second run and the 14.7 is just the sum of respective rows
[3] vps means that the performance is not as stable as on a local machine

@appzuka
Copy link
Member

appzuka commented Aug 26, 2020

This is very interesting as I am currently working on something very similar. As you observe, tsc -b is very fast for subsequent builds. I am hoping to use this by creating a webpack plugin that runs tsc -b at the start of the build so you get this benefit but still a single step workflow.

In the case of 'rebuild on 1st change in non-reference' the fastest build is by 'webpack-dev-server+tsloader, transpileOnly, fork-ts-checker'. This is probably the most important benchmark. Developers want a fast feedback loop when developing and it is probably worth sacrificing a slower production build and/or cold start for webpack-dev-server to achieve this.

I am not surprised that rebuild after changing a reference is slower. ts-loader internally calls tsc -b on the project reference in this case so you get a time similar to the tsc -b plus webpack bundling. I would assume that the references are more stable projects and that most development goes on in the non-references, so maybe this is not so bad.

The only thing that surprises me is that you are not seeing type checking in the case of webpack-dev-server+tsloader, transpileOnly, fork-ts-checker. I note that the times are similar to without fork-ts-checker so I wonder if fork-ts-checker is really working in this setup.

I believe the best setup today is your Option 2 with transpileOnly added (assuming fork-ts-checker can be made to work).

It could be that option 1 (tsc -b -w + webpack-dev-server) is a better option under some conditions (size of project, size of references, whether you are editing the main project or reference). Today that is a messier workflow and may be slower during development so it is hard to recommend.

I'll copy you on my new plugin if it looks promising. It does offer much faster warm starts but I need to understand how to match the current speed for changing a single file in the main project as ts-loader does a great job there and it is probably the most critical use case.

@desmap
Copy link

desmap commented Aug 26, 2020

The only thing that surprises me is that you are not seeing type checking in the case of webpack-dev-server+tsloader, transpileOnly, fork-ts-checker. I note that the times are similar to without fork-ts-checker so I wonder if fork-ts-checker is really working in this setup.

This is also what I didn't get: transpileOnly + fork-ts turns off type checking again. Once fork-ts is in place transpileOnly has to be omitted. I tested this multiple time with deliberate type errors which only popped up if transpileOnly wasn't omitted while fork-ts-checker being enabled. I also did a PR for the docs.

I believe the best setup today is your Option 2

I tend also to option 2 but you could use both once you work a lot on refs but let's see.

I'll copy you on my new plugin if it looks promising

I'd love to.

@noelebrun
Copy link
Author

Hi! All those diagnostics and investigations sounds very promising for the future of references support in ts-loader, nice work!

I just didn't clearly understood: are you still experiencing the multiples re-compiles?

@desmap
Copy link

desmap commented Aug 26, 2020

I just didn't clearly understood: are you still experiencing the multiples re-compiles?

i didn't experience any multi-compiles with ts-loader but my test repo is just two files (a main and a reference file) + the typical project reference boilerplate, so IDK

@desmap
Copy link

desmap commented Aug 26, 2020

Updated table (update in NEW OPTION 2, be aware that latter times were taken at another daytime, this can make some difference on a vps or fork-ts-checker struggles much more with project reference than the rest of the pack):

fyi, 4-core vps[3] benchmarks, reference and non-reference files have each 1,000 functions

tl;dr: UPDATED option 1 is faster on reference builds and warm starts, option 2 on non-reference builds and cold starts, new option 3 even faster on sequential builds but the slowest on reference builds

new tldr: there seems to be something wrong with how tsloader compiles references, so best are OPTION 3 and 1 check also #1174

setup type-checking? initial build w/o changes before (warm start) initial build w/ changes before initial build after rm -r dist (cold start) rebuild on 1st change in non-reference rebuild on 1st change in reference rebuild on 2nd change in non-reference rebuild on 2nd change in reference
OPTION 1 tsc -b -w + webpack-dev-server just bundling tsc's output, aggregateTimeout: 0 1.5s 13s 14.7s[2] 2.3s 3.4s 2.2s 2.4s
OPTION 2 webpack-dev-server+tsloader, fork-ts-checker 5.4s 5.2s 9.6s 1.8s 4.5s 1.1s 3.3s
webpack-dev-server+tsloader - - 9.5s 2.1s 4.2s 1.9s 4.4s
webpack-dev-server+tsloader, transpileOnly - - 8s 1s 4.4s 0.4s 3.7s
webpack-dev-server+tsloader, transpileOnly, tsc noEmit 5.2s 5s 12.2s 1s 6s 0.9s 6s
OPTION 3 webpack-dev-server+babel, tsc noEmit 6.7s 6.8s 6.6s 1.7s 1s 0.3s 1s
NEW OPTION 2 webpack-dev-server+tsloader, transpileOnly, fork-ts-checker 4.7s 4.5s 9.9s 1.2s 5.5s 0.9s 6s
just tsc -b -w without bundling 0s 11.5s 13.2 1.9s 2.9s 1.67s 1.94s
just webpack-dev-server bundling tsc's output, aggregateTimeout: 750 - - 1.56s 0.5s 0.6s 0.4s 0.3s
just webpack-dev-server bundling tsc's output, aggregateTimeout: 0 - - 1.5s 0.4s 0.5s 0.5s 0.4s
webpack-dev-server+tsloader w/ happyPackMode, fork-ts-checker w/semantic+syntatic, threadloader w/infinite pool -[1] - - - - - -

[1] Couldn't get thread-loader to work, got Cannot read property 'options' of undefined
[2] Be aware that it needs a second run and the 14.7 is just the sum of respective rows
[3] vps means that the performance is not as stable as on a local machine

@desmap
Copy link

desmap commented Aug 26, 2020

final verdict: so after this benchmark marathon, I could think that fork-ts-checker might a deal-breaker in a proper DRY monorepo where a lot of references are used. pure tsc is speed-wise ok but still not great and you cannot turn off type-checks.

Which you can with pure ts-loader. So maybe latter is the way to go with type checks in your editor only. Is this good, anyone experience with this setup?

@stale
Copy link

stale bot commented Nov 1, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Nov 1, 2020
@stale
Copy link

stale bot commented Nov 29, 2020

Closing as stale. Please reopen if you'd like to work on this further.

@stale stale bot closed this as completed Nov 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants