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

Implementation of --adjacent-node-modules to support module symlinking to global cache #9456

Closed
wants to merge 5 commits into from

Conversation

ghost
Copy link

@ghost ghost commented Nov 4, 2016

Checklist
  • make -j8 test (UNIX), or vcbuild test nosign (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
Affected core subsystem(s)

Modules

Description of change

Branched from v7.0.0 tag.

Using --adjacent-node-modules cmdline arg, or setting NODE_ADJACENT_NODE_MODULES, adds additional search paths for resolving prefix-less requires (i.e. require('somelib') ).

Details provided in this issue

It's expected this PR will be rejected for now, but there were some who wanted to take a peak first.

Test results

[----------] Global test environment tear-down
[==========] 26 tests from 2 test cases ran. (233 ms total)
[ PASSED ] 26 tests.
running 'python tools\test.py --mode=release addons doctool known_issues message parallel sequential -J'
=== release test-http-chunk-problem ===
Path: parallel/test-http-chunk-problem
Command: C:\src\node\Release\node.exe C:\src\node\test\parallel\test-http-chunk-problem.js
--- TIMEOUT ---
=== release test-process-kill-null ===
Path: parallel/test-process-kill-null
Command: C:\src\node\Release\node.exe C:\src\node\test\parallel\test-process-kill-null.js
--- TIMEOUT ---
[03:37|% 100|+ 1257|- 2]: Done
running jslint

C:\src\node>

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. meta Issues and PRs related to the general management of the project. module Issues and PRs related to the module subsystem. v7.x labels Nov 4, 2016
@@ -42,6 +42,7 @@ _UpgradeReport_Files/
ipch/
*.sdf
*.opensdf
*.VC.db
Copy link
Contributor

Choose a reason for hiding this comment

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

you might want to PR this standalone if this a VC output file resulting from a node build

@joshgav
Copy link
Contributor

joshgav commented Nov 4, 2016

Can this already be accomplished with the NODE_PATH env var? See https://github.com/nodejs/node/blob/master/lib/module.js#L629-L634

@ghost
Copy link
Author

ghost commented Nov 4, 2016

Unfortunately no. The search paths are dependent on where the require() call is made, and change accordingly. NODE_PATH is static within an execution.

Think of it this way. When node was first made, rather than appending '/node_modules' progressively to create a list of search paths like this (copied from docs):

/home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js

They could have just as easily appended '.node_modules' instead leading to this:

/home/ry/projects.node_modules/bar.js
/home/ry.node_modules/bar.js
/home.node_modules/bar.js
/.node_modules/bar.js

And the fundamental way in which the folder hierarchy provides precedence to enable multiple versions of a given module to be used, would still work precisely and as elegantly as it does today, because in both cases they're still folders aligned to the dependency hierarchy.

The key difference is that using '/node_modules' means the dependencies are physically underneath the dependent module's folder, and if there were multiple symlinks to that module's folder from several projects, the dependency tree's of each of those projects would always end up using the same dependencies when require()ing the shared symlinked module.

This is a problem because the version specs of dependencies in package.json are most always specified as a ranges, like '^1.0.0', which means, for various reasons, when a logical dependency tree from package.json is 'rendered' into a physical form you can get different versions of dependencies for various reasons, like just that time has passed and newer releases have been made.

And this means that, for all practical purposes, it's impossible to have one single copy of a module on a machine, that is referenced (symlinked) in many places, and still guarantee in each case the physical dependency trees are deterministic.

However, when '.node_modules' is used rather than '/node_modules', the folder is adjacent to the dependent module and not underneath it, and this is what allows physical dependency trees to vary the versions used on a per-project basis, just as happens today, except now all modules everywhere can by symlinked to a single physical copy, most likely stored in a global location.

This PR is extremely simple. When the search path list is being created, when ever '/node_modules' is appended to create a new path, this patch then adds a second path with '.node_modules' appended! Thats it! This lets modules still resolve exactly as today, via '/node_modules', but also by '.node_modules'. It's the best of all worlds: Backwards compatible, allows for the same dependency trees as today, but now only a single physical copy of a module need be physically stored somewhere. This means in practice dozens of gigabytes of storage is not wasted, that moving and deleting of node based projects is lickity split, and 'rendering' a dependency trees can by done entirely by symlinking to the modules, and not copying.. super super fast.

Reading this issue I created might offer more clarity, as it has an example of this.

@ghost
Copy link
Author

ghost commented Nov 5, 2016

@joshgav Just wanted to thank you for taking a seemingly objective first look at this, and attempting to offer another solution. It seems most others just hear "Modules" and "change" and immediately dismiss even trying to understand what the issue is, the simplicity of the solution, and the potential positive impact. Given your status here, was wondering if you had any insight on some of the key decision makers, etc., and how they might be better approached to at least take a fair look at this like you seemed to.

@jasnell
Copy link
Member

jasnell commented Nov 7, 2016

I haven't yet had an opportunity to review the PR, but right off the bat this would need to target master and not the v7.x branch. We don't land new features or capabilities directly into the release branches unless they've been landed in master first.

@jasnell jasnell added the semver-minor PRs that contain new features and should be released in the next minor version. label Nov 7, 2016
@ghost
Copy link
Author

ghost commented Nov 7, 2016

@jasnell Thanks for the input. It was made quite clear by others this PR will never be accepted by node.js, simply because it's an enhancement to the Modules resolution algorithm (regardless that it's opt-in). The thinking was that developers who still want this feature, could build the branch knowing it was based on a released version of node, rather than an in-progress version. I was told by someone they would not review without a PR here, which is why I made the PR.

Would you still recommend it be based from master?

@jasnell
Copy link
Member

jasnell commented Nov 7, 2016

Ok, given that then I think it's fine.

On Sunday, November 6, 2016, Paul D. Hester [email protected]
wrote:

@jasnell https://github.com/jasnell Thanks for the input. It was made
quite clear by others this PR will never be accepted by node.js, simply
because it's an enhancement to the Modules resolution algorithm (regardless
that it's opt-in). The thinking was that developers who still want this
feature, could build the branch knowing it was based on a released version
of node, rather than an in-progress version. I was told by someone they
would not review without a PR here, which is why I made the PR.

Would you still recommend it be based from master?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#9456 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAa2efYWWKj30xGXNNOx8TEqDlue_AKKks5q7nRggaJpZM4KpKiO
.

@ghost
Copy link
Author

ghost commented Nov 7, 2016

Outside the politics, your opinion on the PR and what it enables would be greatly appreciated.

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. meta Issues and PRs related to the general management of the project. module Issues and PRs related to the module subsystem. semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants