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

refactor: update to tsconfck3 with lazy cache #14234

Merged
merged 8 commits into from
Sep 15, 2023

Conversation

dominikg
Copy link
Contributor

@dominikg dominikg commented Aug 29, 2023

Description

tsconfck 3 lazily caches found and parsed tsconfig files to ensure minimal use of fs without having to use the root or findAll + tsconfigPaths options.

This PR updates to a beta release to gather feedback. vite beta bundling a tsconfck beta should be fine, before releasing vite5.0 tsconfck 3.0 is going to be released and added.

Additional context

The removal of async init and root options means we no longer have to do the song and dance to initialize it, however the way it was tied to root/workspace root could mean it wasn't meant to be shared before. It should be safe now but extra care is needed to ensure we don't break stuff.

It should also be checked how perf is affected. cold start/ready should become slightly faster while page ready could become a little slower. hmr should be unaffected.

What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

Before submitting the PR, please make sure you do the following

  • Read the Contributing Guidelines.
  • Read the Pull Request Guidelines and follow the PR Title Convention.
  • Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
  • Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g. fixes #123).
  • Ideally, include relevant tests that fail without this PR but pass with it.

@dominikg
Copy link
Contributor Author

@sheremet-va would be great if you could test this with your windows setup that was slow on findAll.

@fi3ework / @sapphi-red what's the best way to benchmark the code in this PR (comparison between current main and this, startup and hmr in a project with many ts files)

@stackblitz
Copy link

stackblitz bot commented Aug 29, 2023

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@sapphi-red sapphi-red added this to the 5.0 milestone Aug 31, 2023
@sapphi-red
Copy link
Member

It may be a good idea to do the following cases:

  • No tsconfig.json exists in the ancestor path
  • Deep directory with ts files in each directory
  • One directory with a large number of ts files

Triggered the benchmark CI: https://github.com/vitejs/vite-benchmark/actions/runs/6032434823

@sapphi-red
Copy link
Member

Hmmm, the benchmark CI is failing for some reason. Maybe the recent breaking changes broke it

@dominikg
Copy link
Contributor Author

that might be a legit fail. for some reason the perf-2 benchmark doesn't contain a tsconfig.json file even though it uses vite.config.ts and tsx files.

tsconfck should still return an empty object in that case and vite then just uses defaults, but it seems something is different in v3, even though the testcase in tsconfck passes for this. gotta investigate more. cc @fi3ework for the benchmark thing. not sure if the missing tsconfig is on purpose or an accident

@dominikg
Copy link
Contributor Author

dominikg commented Sep 2, 2023

benchmark call should work again now, here are the results of a local run


Benchmark for pull request #14234

Meta Info

pull request link#14234
SHA of compare 0cd6bf29
SHA of compare 1dominikg/vite@4d984e4
repetition5

Benchmark Result

Case 1: vite 2.7 slow

Details
refstart up meanstart up medianserver start meanserver start medianfcp meanfcp median
cd6bf293657364721221231573150
dominikg/vite@4d984e43595359521121130903088
refstartserverfcp
cd6bf29---
dominikg/vite@4d984e4-52 (-1.43%) ⚡️-1 (-0.47%) ⚡️-62 (-1.97%) ⚡️

Case 2: 1000 React components

Details
refstart up meanstart up medianserver start meanserver start medianfcp meanfcp median
cd6bf294159419225825835493583
dominikg/vite@4d984e44118410925725835153504
refstartserverfcp
cd6bf29---
dominikg/vite@4d984e4-83 (-1.98%) ⚡️--79 (-2.20%) ⚡️

note that the results fluctuate a bit, so it's not clear that the new tsconfck is faster in this benchmark, it isn't slower though and does less work up front in huge projects so i'll take it.

@dominikg
Copy link
Contributor Author

dominikg commented Sep 3, 2023

The removal of the "root" option means it'll also continue to search for tsconfig files outside of workspace root, which is more in line with typescripts own behavior at the expense of added risk that files outside the workspace root can change the outcome of a build - i would not recommend such a setup and maybe it warrants a warning log.

Another thing to consider is that findAll ignored node_modules, with that gone, find will now use the closest tsconfig for files inside node_modules too, so with the files below

# some lib containing ts files in src and a tsconfig.json
node_modules/some-lib/tsconfig.json  
node_modules/some-lib/src/index.ts
# vite root contains tsconfig.json and src
src/something.ts
tsconfig.json 

the old implementation with tsconfck v2 and findAll would use root tsconfig.json for node_modules/some-lib/src/index.ts, while with tsconfck v3 would find and use node_modules/some-lib/tsconfig.json

Now there shouldn't be published libraries that come with ts instead of js files, but if you had a locally linked package inside node_modules, it could happen 🤔

@sapphi-red
Copy link
Member

that might be a legit fail. for some reason the perf-2 benchmark doesn't contain a tsconfig.json file even though it uses vite.config.ts and tsx files.

Ah, I see. The reason it was missing tsconfig.json was because the original repo was missing that and I didn't notice that when forking from it.

The removal of the "root" option means it'll also continue to search for tsconfig files outside of workspace root, which is more in line with typescripts own behavior at the expense of added risk that files outside the workspace root can change the outcome of a build - i would not recommend such a setup and maybe it warrants a warning log.

I think we can have a warning for this.

Another thing to consider is that findAll ignored node_modules, ...

I think we can skip the tsconfigs in node_modules. esbuild does this as well (there were some discussion about this at evanw/esbuild#3019). For foo/node_modules/some-lib/src/index.ts, I guess using a tsconfig resolved from foo would make sense.

For locally linked packages, Vite will pass the real path to tsconfck (if preserveSymlinks: false which is set by default) so it won't be a problem.

@dominikg
Copy link
Contributor Author

dominikg commented Sep 4, 2023

It would be fairly easy to add a "jump out of node_modules" here https://github.com/dominikg/tsconfck/blob/version-3/packages/tsconfck/src/find.js#L42

like

const i = dir.indexOf('/node_modules/');
if(i>-1) {
  dir = dir.slice(0,i);
}

however does esbuild pick up tsconfig outside node_modules or outright ignore all tsconfig files and go with defaults?
And is it the same with typescript itself or would that honor it.

I really hope they do it consistently to avoid having another option 🙈

@dominikg
Copy link
Contributor Author

dominikg commented Sep 4, 2023

of course typescripts own find config does not skip over node_modules. dominikg/tsconfck#123

…h lazy cache create and use direct cache access to avoid one promise wrap/unwrap
@dominikg
Copy link
Contributor Author

dominikg commented Sep 4, 2023

latest tsconfck 3 beta ignores files in node_modules by default, bumped this PR to it got rid of init altogether in favor of lazy cache create.

local bench with it:

Benchmark for pull request #14234

Meta Info

pull request link#14234
SHA of compare 0cd6bf29
SHA of compare 1dominikg/vite@6a71ed5
repetition5

Benchmark Result

Case 1: vite 2.7 slow

Details
refstart up meanstart up medianserver start meanserver start medianfcp meanfcp median
cd6bf293713369921221231793197
dominikg/vite@6a71ed53668362721121131683133
refstartserverfcp
cd6bf29---
dominikg/vite@6a71ed5-72 (-1.95%) ⚡️-1 (-0.47%) ⚡️-64 (-2.00%) ⚡️

Case 2: 1000 React components

Details
refstart up meanstart up medianserver start meanserver start medianfcp meanfcp median
cd6bf294192417526125935823565
dominikg/vite@6a71ed54139415525725735313546
refstartserverfcp
cd6bf29---
dominikg/vite@6a71ed5-20 (-0.48%) ⚡️-2 (-0.77%) ⚡️-19 (-0.53%) ⚡️

@dominikg
Copy link
Contributor Author

dominikg commented Sep 4, 2023

the test fail seems to happen due to insufficient error handling inside tsconfck. cache evicts entries that error automatically but somehow it seems to get stuck on a promise that never settles.

@dominikg
Copy link
Contributor Author

dominikg commented Sep 4, 2023

this PR in tsconfck dominikg/tsconfck#125 caches errors instead of eviction. After a parse error, a file has to be edited to correct that error and vite clears the tsconfck cache on changes, so it would get parsed once again.

Speaking of reparsing, in some situations we might not have to throw away the whole cache or invalidate the complete module graph but just reparse that tsconfig and invalidate files matching the old (and new) config. But determining this safely and then finding out if invalidating some files is faster than reloading everything is hard.

@sapphi-red
Copy link
Member

however does esbuild pick up tsconfig outside node_modules or outright ignore all tsconfig files and go with defaults?

Ah, it seems esbuild simply ignores and go with defaults.
evanw/esbuild@ab7921d#diff-ff3593e6a6cb00f927118c829760e054ccca7686eae492f9f4f18b9b851a9a20R1391-R1418

@aleclarson
Copy link
Member

Can we expose the cache on ResolvedConfig so vite-tsconfig-paths can reuse it?

@dominikg
Copy link
Contributor Author

Can we expose the cache on ResolvedConfig so vite-tsconfig-paths can reuse it?

we would have to expose the complete tsconfck options or even better the function that returns the config to prevent differences

@sheremet-va
Copy link
Member

we would have to expose the complete tsconfck options or even better the function that returns the config to prevent differences

I think having a method on a server to get tsconfig for a specific file might be a good idea for performance reasons. Having the same for package.json would also be phenomenal, but it’s out of the scope of this issue of course.

Exposing cache itself seems risky and limits design space I think (need to release a breaking change if interface changes or something)

@aleclarson
Copy link
Member

I think having a method on a server to get tsconfig for a specific file might be a good idea for performance reasons.

It should be available in both dev and build mode

@dominikg
Copy link
Contributor Author

however does esbuild pick up tsconfig outside node_modules or outright ignore all tsconfig files and go with defaults?

Ah, it seems esbuild simply ignores and go with defaults. evanw/esbuild@ab7921d#diff-ff3593e6a6cb00f927118c829760e054ccca7686eae492f9f4f18b9b851a9a20R1391-R1418

PR to change tsconfck to this behavior: dominikg/tsconfck#128

Would it be better if this was done inside vite though? This is more specific to esbuild behavior than typescript itself.
Or tsconfck could invert the option to ignoreNodeModules and vite would have to set it.

@dominikg
Copy link
Contributor Author

went ahead and changed it to ignoreNodeModules and have vite opt in to that behavior.

@dominikg dominikg marked this pull request as ready for review September 14, 2023 08:00
@patak-dev
Copy link
Member

/ecosystem-ci run

@vite-ecosystem-ci
Copy link

vite-ecosystem-ci bot commented Sep 14, 2023

📝 Ran ecosystem CI: Open

suite result
analogjs ✅ success
astro ✅ success
histoire ❌ failure
ladle ❌ failure
laravel ✅ success
marko ✅ success
nuxt ✅ success
nx ✅ success
previewjs ✅ success
qwik ✅ success
rakkas ✅ success
sveltekit ✅ success
unocss ✅ success
vite-plugin-pwa ✅ success
vite-plugin-ssr ✅ success
vite-plugin-react ✅ success
vite-plugin-react-pages ❌ failure
vite-plugin-react-swc ✅ success
vite-plugin-svelte ❌ failure
vite-plugin-vue ✅ success
vite-setup-catalogue ✅ success
vitepress ✅ success
vitest ✅ success

Copy link
Member

@sapphi-red sapphi-red left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@bluwy
Copy link
Member

bluwy commented Sep 15, 2023

Merging this. We can bump to a stable version of tsconfck before we release a stable.

@bluwy bluwy merged commit 6e0b0ee into vitejs:main Sep 15, 2023
11 checks passed
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.

None yet

6 participants