Closed berickson1 closed 2 years ago
Your example show cases example where the change to unrelatedTypes.ts does not cause any errors.. But thats not always true.. Eg. consider this tsc-watch scenario that we test with its output here. Now assume that a.ts
is in different project instead.. You can import only b.ts but change c.ts can cause new errors as well as changes in what needs to happen in your project. So its not update. Note that we do not have a way to detect unused types or something like that. Anything that exports and changes your declaration file is what is used to determine granularity of what needs update. (So file is a unit instead of each type)
I believe what I talked about would in-fact find errors. I understand that there is likely design constraints as a limiting factor.
If you think about type consumption as a directed tree (from the root definition to the branches/leaves). A changes to any type node needs to propagate upwards away from the root and force a re-check of all usages at all nodes above. In the case of the unrelatedType
, it's never consumed and has no references/usages, so type-checking could short early. If it was referenced, like in your a/b/c example, the change would invalidate unrelatedType
(c.ts) and all it's usages (b.ts). That, in turn, would invalidate it's tree, causing a cascading type-cache invalidation in a.ts as well. Especially in codebases that have have high compile-time costs, this could be beneficial.
The above covers the the second portion of my analysis.
I still think that the first portion of my bug about material UI adding 500ms to the total build for every usage in a composite project is valid. The solution likely boils down to some level of caching as originally discussed in #46856
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.
@sheetalkamat FYI - don't know if you've read this before the bot decided this ticket was dead
But thats the thing.. our graph calculation is based on d.ts emit of a file and not type changes. So what you are saying isn't feasible that too across projects
Bug Report
🔎 Search Terms
typescript composite project performance type material ui
🕗 Version & Regression Information
Tested on
@latest
and@next
. I do NOT believe this is a regression, but it is a performance issue for us.Please keep and fill in the line that best applies:
⏯ Playground Link
Unfortunately, there's no good way to provide a playground, but see repo linked. This repo contains 22 composite projects:
button
packages - which are simply usages of MUI Button (These cause each project's build to take an additional 500ms)core
package - this is utilized by all the buttonszoo
package - this imports a button (ultimately isn't really needed in this example)💻 Code
yarn install
yarn watch
(this runstsc -b --watch
in the root)core/utilitites.ts
andcore/urelatedTypes.ts
makeRandomName
incore/utilities.ts
. Observe built time (A)UnrelatedType
incore/unrelatedTypes.ts
. Observe build time (B)🙁 Actual behavior
Build A takes ~6s Build B takes ~17s
In this case, updating an un-used and unrelated type in downstream packages causes a full re-build of the project. Unfortunately, some expensive types (described below in analysis section) cause this to be non-trivially expensive. Updating the implementation (step 5), rather than types, results in a quick rebuild since the downstream projects don't detect any changes in typings.
🙂 Expected behavior
Build types A and B should be similar - clocking in around 6s on my machine
My Analysis
I think this ultimately boils down to 2 related issues (please let me know if you'd rather this be tracked in separate reports)
Real-world use case
I recognize that the example repo provided is somewhat contrived, so I’ll share how we’re bumping into this. Our repository has 100+ typescript project references that are wired together via projectReferences. Under the hood of our application we utilize GraphQL + Apollo, which has type-generation hooked up. This type-generation creates a collection of fragment/query/document types in a common package, which we then can import/access across the application (@myScope/gql-types). When a developer updates a GraphQL Query, the base @myScope/gql-types package gets updated, which triggers all packages that import any Queries to be re-compiled. We also take a dependency on MaterialUI in our packages, which increases the overhead of the incremental compile.
I would have initially hoped that skipLibCheck would have reduced the overhead of MUI type-checking, however I think the complex generics that are utilized in this (and other MUI components) still results in some heavy type inferencing.
Test Environment
2020 M1 MBP - 16GB Ram Node 16.8.0 Typescript: 4.5.5
Potentially Related Issues/Discussions
Relates: https://github.com/microsoft/TypeScript/issues/47137 - This issue could potentially be addressed by something similar to d.ts tree-shaking proposed here https://github.com/microsoft/TypeScript/issues/43717