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

perf(resolve): refactor tryFsResolve and tryResolveFile #12542

Merged
merged 5 commits into from Mar 23, 2023

Conversation

patak-dev
Copy link
Member

@patak-dev patak-dev commented Mar 22, 2023

Description

tryFsResolve was calling tryResolveFile, that recursively would call tryFsResolve if the file was a directory. The code was quite complex to follow, and optimizations were added to short-circuit some redundant checks.
The function had to deal with:

  • postfix
  • Possibility of a # in a node_modules path
  • options.extensions
  • .js to .ts resolution
  • tryIndex
  • tryPrefix (/index -> _index for .sass)

This PR deals with the # in node_modules path and postfix upfront in tryFsResolve, creating a new tryCleanFsResolve that doesn't need to deal with the first two requirements.

This means that from now on if there is a # in node_modules, we will first check the whole resolution for the complete fsPath first. Before, these checks were interleaved. I think this is the proper order, and it shouldn't affect much because only a few deps have # in their paths.

The PR also removes tryFsResolve, flattening the checks directly in tryCleanFsResolve. The new function is more verbose but we no longer have recursion into tryFsResolve. All the checks and the order are now clear by looking at this function (it is terrible how many things we need to check).

Because all the checks are in the same function, it is easier to reuse statSync calls and to group all the checks that need path.dirname(file) to be a directory and bail out from all of them if not.


What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

@stackblitz
Copy link

stackblitz bot commented Mar 22, 2023

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

@patak-dev patak-dev marked this pull request as ready for review March 22, 2023 21:16

// Dependencies like es5-ext use `#` in their paths. We don't support `#` in user
// source code so we only need to perform the check for dependencies.
// We don't support `?` in node_modules paths, so we only need to check in this branch.
Copy link
Member Author

Choose a reason for hiding this comment

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

The function no longer used the splitFileAndPostfix util because we can avoid a redundant check if we know the result of the two indexOf.

Copy link
Contributor

Choose a reason for hiding this comment

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

if the index is used later and it is important to split path from query and hash, foo#something?bla could trip it

Copy link
Member Author

Choose a reason for hiding this comment

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

It was always the case that foo#something?bla would be split as foo#something + ?bla because a URL needs to have the ? before the #. Check how splitFileAndPostfix is working (that is being used in other places). If something is broken for node_modules path that has #, we are missing a test. Do you see a case that wouldn't work? (there definitely could be out of these two functions, but this PR shouldn't change that)

Copy link
Contributor

@dominikg dominikg Mar 23, 2023

Choose a reason for hiding this comment

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

If it works like the previous implementation it's fine i guess (at least not a regression). But from a url perspective, a hash containing a questionmark is allowed, right? so https://example.com/path#foo?bar would have no query and hash foo?bar.
So to safely extract the path, you'd have to use the lower first index of both.

@patak-dev patak-dev added p4-important Violate documented behavior or significantly improves performance (priority) performance Performance related enhancement labels Mar 22, 2023
if (
options.mainFields[0] === 'sass' &&
!options.extensions.includes(path.extname(entry))
) {
entry = ''
options.skipPackageJson = true
Copy link
Member Author

Choose a reason for hiding this comment

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

This was modifying the options object for every entry. I think there was a bug here we never catched. I refactored skipPackageJson to pass it directly to tryFsResolve now.

@patak-dev
Copy link
Member Author

/ecosystem-ci run

@vite-ecosystem-ci
Copy link

vite-ecosystem-ci bot commented Mar 22, 2023

📝 Ran ecosystem CI: Open

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

@patak-dev
Copy link
Member Author

✅ Astro is back green! 🎉

Copy link
Member

@bluwy bluwy left a comment

Choose a reason for hiding this comment

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

This was much easier to digest than expected. LGTM. Got a couple nits below, but I like this new flow a lot.

packages/vite/src/node/plugins/resolve.ts Outdated Show resolved Hide resolved
packages/vite/src/node/plugins/resolve.ts Outdated Show resolved Hide resolved
patak-dev and others added 2 commits March 23, 2023 08:29
Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com>
Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com>

// Dependencies like es5-ext use `#` in their paths. We don't support `#` in user
// source code so we only need to perform the check for dependencies.
const tryUnsplitted = fsPath.includes('#') && fsPath.includes('node_modules')
Copy link
Member Author

Choose a reason for hiding this comment

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

If there was a # before the query, before we were checking for tryUnsplitted branches with the full path including the query and these were all redundant checks.

bluwy
bluwy previously approved these changes Mar 23, 2023
@patak-dev patak-dev enabled auto-merge (squash) March 23, 2023 07:45
@patak-dev patak-dev disabled auto-merge March 23, 2023 09:15
@patak-dev patak-dev merged commit 3f70f47 into main Mar 23, 2023
12 checks passed
@patak-dev patak-dev deleted the refactor/skip-package-json branch March 23, 2023 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p4-important Violate documented behavior or significantly improves performance (priority) performance Performance related enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants