-
Notifications
You must be signed in to change notification settings - Fork 29.9k
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
Don't resolve symlinks when requiring #3402
Comments
This would break |
if you are requiring dep1, and it is a symlink, and it doesn't have dep2 in its path then something is off is it not? Should the module not include its own node_module folder? That being said flat dependencies in npm@3 do offer a weird edge case to this. But it is worth bringing up that I am pretty sure they are deprecating peer dependencies. |
@Trott why would it? In theory, everything that works with the real path should also work fine with the virtual path. The only real problem that i see is when a module gets required multiple times through different symlinks it would not be cached by npm and get loaded multiple times. But if that really happens, something is badly designed i think. @thealphanerd I don't think the need for peer dependencies will go away in the future. |
I've also asked for a new npm command that would only work if we fix the behavior of require like i suggested here: npm/npm#10000 (comment) |
@VanCoding I was thinking of certain edge cases but I wasn't thinking very deeply about it, so yeah, that particular comment may be a non-issue. The real point I was sorta kinda trying to gently make was better put by @othiym23 (emphasis added):
Any semver-major change to |
I know, but I think the current behavior maybe even counts as a bug because
|
The litmus test is this: is there a non-zero chance the proposed change is going to break someone's existing application? If the answer is 'yes' (and I think it is), then it should be rejected. |
Well, how are we going to calculate that chance? And what does a zero Let's look at it like this: one can always get the real path from the So even if we break some modules, isn't the right decision to fix this? I But it of course is your decision.
|
@VanCoding, maybe hard links would help. I haven't tried it. |
@dlongley You can't hardlink a directory I think? I am having the exact same issue as @VanCoding and I'm also a bit confused by the current behaviour...? I would expect a linked package to resolve dependencies based on the location it was linked to. It should of course check it's own node_modules first, but when going back "up the tree" I would expect it to check the folder structure it was linked to, not where it was linked from. |
No, you can't, but maybe you could write a script to create a mock directory and hard link any
Me too, but I believe this has been discussed before -- and there may be projects out there that are depending on the current behavior. We'll just need to come up with a way to specify that the other behavior is desired. |
As I said before:
And as it seems...
|
@dlongley, I don't like it. I'd rather 'keep it simple ..' in the long-term. @VanCoding makes a compelling argument. Perhaps we should make this minor 'breaking change', and just add an opt-out capability. The opt-out should be removed in a future version.. |
I agree with @VanCoding's argument.
👍 I'm in favor of this if it can get consensus. |
That is an addition, so |
If someone wants to put together a PR for this (with the understanding that, again, the bar for this is very, very high and so even if it's a Great Idea and an Excellent Implementation, it's still very likely that this Will Not Happen), it might be interesting to use https://github.com/nodejs/citgm (if that tool is ready for general use?!) to see if anything Too Big To Fail in the ecosystem chokes on the change. (To head off the obvious and explain the bold comment above: Yes, it's easy to fix any modules that break. That's not good enough though. Here's the deal: Let's say this breaks the async module. Fixing it in a new version of async is theoretically no problem. But then getting the thousands and thousands of modules that depend on async to update to the fixed version is a huge problem. And getting everyone using those thousands and thousands of modules to update those modules to fixed versions... This is why a stable and imperfect module API is vastly preferable to a dynamic module API.) Of course, if there was a way to confirm that no modules on npm depend on the current behavior, that would go a long way (in my opinion, anyway) towards making the change palatable. I have no idea how one would go about demonstrating that, though. But you can use |
@Fishrock123, I tend to think my suggestion should wait until the next @Trott, These are good points. The last thing sysadmins want is trouble when upgrading a datacenter to a new version of Node.js. We should also consider any arguments for current behavior besides compatibility. Are there cases where the current behavior is more intuitive than the proposed change? If not then I think the proposed change should be implemented sooner or later. I know that Modules are at Stability 3 - Locked.
There are good ways to introduce a breaking change over a period of time. Statistics would indicate the best course of action - even if it means extra work on the front end before this change can be implemented. |
This is causing me pain right now. I'm working on an enhancement to a library that automagically loads plugins by doing I think this behavior is unexpected, especially given the interaction with From the modules docs:
I suppose this is ambiguous, but I would argue that the "parent directory" should be relative to the path used to load the module. If I do @Trott it might be worth taking a look at https://github.com/brson/taskcluster-crater to see how they test the rust ecosystem against potentially dangerous changes. |
@fenduru 👍 Looking at the examples from the documentation, it is, IMO, unexpected behavior for a file that happens to be a symlink to behave differently. I would expect it to behave the same as any other file, which is as @fenduru described. Furthermore, the documentation gives one good reason for the way module searching is performed:
The fact that searching does not work this way with symlink'd modules makes it very difficult to make use of localized dependencies (this is the chief complaint). As pointed out above, it also causes different (and unexpected) behavior with |
Just a note here that a fix to the unexpected behavior shouldn't change the existing behavior for module identifiers that are native or that begin with '/', '../', or './'. In those latter three cases it does make sense to use |
I also found this require/symlink behavior to be unexpected and undesirable. It goes against common UNIX practice. Out of curiosity - does node on Windows also have this require/symlink behavior? (At one time Windows did not support symlinks). If node behavior on UNIX and Windows differ in this regard that would strengthen to case against symlink resolving in require() on UNIX to be consistent. At the very least an optional node command line flag could be introduced to disable resolving symlinks when require()ing. |
@kzc,
Assuming that It looks like the problem is that no distinction is made between loading a module with an identifier that starts with '/', '../', or './' and one that doesn't -- all are given the |
Regardless of whether require()d modules have relative or absolute paths they still could be converted to canonicalized absolute paths without resolving symlinks. I see the need for the module cache to use absolute paths so that it knows when it's dealing with the same module referenced from various different relative paths. But if someone explicitly introduces a symlink in the path of a module then I'd argue that most would expect it to be treated differently than the symlink resolved version according to its non-resolved directory position. |
@kzc,
This is problematic for the case shown here: http://grokbase.com/t/gg/nodejs/12cbaygh7a/require-resolving-symlink
|
The node start script is a special case that could be symlink resolved if the file has a shebang or a non .js suffix. |
I'm having the same problem as @fenduru.
This is unexpected. It only happens when symlinked / npm link'd. In a normal installation everything works as expected. Since the directory is actually included in 👍 |
Symlinking can be fixed, and works great :) |
Since this issue has the discuss label, I thought I could ask here ... The second best thing to being able to do Which version of the behavior would allow the following?
|
…solved See nodejs/node#3402 for more details
* Preliminary support for local dependencies * Fixed building packages with no dependencies * Transitive local dependencies * Don't resolve workspace dependencies separately * Typo fix * Test case for workspace dependencies * Copy workspace dependencies, otherwise their dependencies can't be resolved See nodejs/node#3402 for more details * Let mkYarnModules determine its own name * Don't use passAsFile * Got rid of a leftover comment
@majid4466 symlinking that node_modules dir should work with the current node. As for the original opening question: dep1 probably shouldn't require dep2, but instead provide a factory that can produce whatever based on dep2. The factory could have a meta data property to declare which other modules the app (or a plugin manager) needs to provide. It's one flavor of dependency injection. |
Currently, Node.js resolves symlinks when requiring and then uses the real location of the package/file as its __filename and __dirname instead of the symlinked one.
This is a problem because symlinked modules don't act the same as locally copied modules.
For example:
works, but
does not, because dep1 does not act like it's located in the node_modules directory of module and thus cannot find dep2.
This is especially a problem when one wants to symlink modules that have peer-dependencies.
Therefore, I suggest changing the behavior to no longer resolve symlinks.
What do you think?
The text was updated successfully, but these errors were encountered: