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

fix(ssr): use tryNodeResolve instead of resolveFrom #3951

Merged
merged 2 commits into from
Nov 11, 2021

Conversation

aleclarson
Copy link
Member

@aleclarson aleclarson commented Jun 24, 2021

Description

This PR makes it so resolve.dedupe and mode are respected in SSR when resolving import specifiers.

Todo

  • Add tests for SSR module resolution

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 Commit 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.

@aleclarson aleclarson added p3-minor-bug An edge case that only affects very specific usage (priority) needs test labels Jun 25, 2021
@aleclarson

This comment has been minimized.

@aleclarson
Copy link
Member Author

I've added a commit that overrides Module._resolveFilename in build mode so that resolve.dedupe is respected. See here: 17eb919

@aleclarson aleclarson force-pushed the feat/ssr-node-resolve branch 3 times, most recently from d675cf0 to 012dc97 Compare June 27, 2021 20:06
@Shinigami92
Copy link
Member

Seems this PR has some errors, pls fix them and revert the draft status after the tests passes

Copy link
Collaborator

@benmccann benmccann left a comment

Choose a reason for hiding this comment

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

Does resolveFrom also need to be updated to tryNodeResolve in ssrExternal? It looks like this PR will need to be rebased, btw.

@jplhomer
Copy link
Contributor

Hiya @aleclarson I read somewhere that this PR also adds support for exports for SSR module imports during SSR — is that true? If so, anything I can do to help move this forward?

@aleclarson
Copy link
Member Author

aleclarson commented Sep 14, 2021

Does resolveFrom also need to be updated to tryNodeResolve in ssrExternal?

@benmccann Seems to be the case already

entry = tryNodeResolve(

I read somewhere that this PR also adds support for exports for SSR module imports during SSR — is that true?

@jplhomer Correct

anything I can do to help move this forward?

Evan wants integration tests for SSR module resolution. So you could update an SSR playground (eg: ./packages/playground/ssr-react) with some/all of the possible SSR-specific edge cases around import:

  • is .js preferred over .mjs
  • is pkg.main used instead of pkg.module (in package.json)
  • is module condition in pkg.exports ignored
  • is node condition in pkg.exports respected
  • are relative imports handled properly
  • does resolve.dedupe work as expected in production

I've tested all those cases manually and the implementation is simple enough, so I don't think the juice is worth the squeeze (hence why I haven't written tests; also I use my own fork). Nonetheless, it's what is needed to merge this. :)

@benmccann
Copy link
Collaborator

benmccann commented Nov 9, 2021

@benmccann Seems to be the case already

What about this line?

const depRoot = path.dirname(resolveFrom(`${id}/package.json`, root))

It would be nice to remove the export where resolveFrom is declared to ensure that it's not used elsewhere

I also wonder if nestedResolveFrom should be updated to use tryNodeResolve

@aleclarson
Copy link
Member Author

What about this line?

Using tryNodeResolve there wouldn't change anything. Do you disagree?

It would be nice to remove the export where resolveFrom is declared to ensure that it's not used elsewhere

I also wonder if nestedResolveFrom should be updated to use tryNodeResolve

I don't see what these changes would fix. Can you elaborate?

@benmccann
Copy link
Collaborator

Using tryNodeResolve there wouldn't change anything. Do you disagree?

I agree with that. I was somewhat thinking it might save people from accidentally using the wrong one if there's only one implementation and that it would allow us to remove the dependency on resolve, which could be nice. But resolveFrom should be fine for resolving package.json, so am fine to leave it as is for now as well

I don't see what these changes would fix. Can you elaborate?

This one I do think may cause an issue. nestedResolveFrom will use browserify/resolve, which does not support exports in package.json (browserify/resolve#222). That means #3953 will still not be fixed by this PR. E.g. if you have a Svelte library with a transitive dependency which has an exports map, but no main or module declared in its package.json, then it wouldn't be able to resolve it properly

There's some possibility we wouldn't need nestedResolveFrom anymore. @bluwy added it to support including / excluding transitive dependencies in optimizeDeps, but he's also since added an experimental.prebundleSvelteLibraries option to vite-plugin-svelte. If we were able to turn that on for all users and migrate users to it then we wouldn't need to smartly detect which transitive dependencies of Svelte libraries to include / exclude from optimizeDeps. But I don't know if anyone else depends on the feature and it might be nice to have it available for awhile still until we really prove out experimental.prebundleSvelteLibraries and make sure it works in all cases

Comment on lines 378 to 379
basedir = path.dirname(importer)
basedir = fs.realpathSync.native(path.dirname(importer))
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure why we need fs.realpathSync.native for this. Perhaps a comment could help explain 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.

I don't remember why I added it xD

Removing for now..

Comment on lines 489 to 494
const pkgPath = resolveFrom(`${id}/package.json`, basedir)
const pkgPath = resolve.sync(`${id}/package.json`, {
basedir,
preserveSymlinks
})
Copy link
Member

Choose a reason for hiding this comment

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

I think we can continue using resolveFrom for this as the main branch now supports preserveSymlinks.

@@ -375,12 +376,12 @@ export function tryNodeResolve(
path.isAbsolute(importer) &&
fs.existsSync(cleanUrl(importer))
) {
basedir = path.dirname(importer)
basedir = fs.realpathSync.native(path.dirname(importer))
} else {
basedir = root
}

Copy link
Member

Choose a reason for hiding this comment

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

To further elaborate Ben's comment about nestedResolveFrom, which would be on this line in the main branch. It's currently used to resolve optimiseDeps.include with syntax like my-lib > some-other-lib. It's probably fine to not update nestedResolveFrom as it's currently used to resolve CJS dependencies only, but yeah ideally we want to move away from it too.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for clarifying. The change to nestedResolveFrom can be done in a future PR 👍

@aleclarson aleclarson marked this pull request as ready for review November 10, 2021 20:51
@patak-dev
Copy link
Member

@benmccann @bluwy would you both review and approve this PR for inclusion? I think we could target the current beta

Copy link
Collaborator

@benmccann benmccann left a comment

Choose a reason for hiding this comment

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

looks good from my end

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.

I'm not the most familiar with SSR side of things, but the resolve part looks good to me.

@patak-dev patak-dev merged commit 87c0050 into vitejs:main Nov 11, 2021
@bluwy bluwy mentioned this pull request Nov 17, 2021
9 tasks
@lovasoa
Copy link
Contributor

lovasoa commented Dec 28, 2021

This pr might be the root cause of sveltejs/kit#3118

It looks like it is choking on https://github.com/mapbox/node-pre-gyp/blob/v0.11.0/lib/pre-binding.js#L20

@Niputi
Copy link
Contributor

Niputi commented Dec 28, 2021

@lovasoa please open a new issue with a reference to this one and a reproduction instead of commenting

@lovasoa
Copy link
Contributor

lovasoa commented Dec 28, 2021

I already reported this issue to @sveltejs, they'll open an issue here if they find it necessary.

But as I found this suspicious pr, I wanted to mention the sveltejs issue here in case it helps with debugging, or it rings a bell to the original author of the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs test p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants