-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
Suggestion: Centralized package repository that support multiple versions of a package #25581
Comments
That's up to the package manager (npm, yarn, etc), that's not really within node's remit. The popular ones cache packages locally however (e.g. The disk space argument isn't that strong in this age of multi-TB hard drives. (It's come up before.) |
What could a package manager do if node does not load modules that the package manager installed? (I'm refering to a centralized package repository)
The popular ones copy files from cache to local
Why handicap your users? You do you assume/demand every user to have TB of disk space? Even if they have TB of disk space, why prevent them to use that space more efficiently? Efficiency is a feature, your counter-argument is not as strong. (BTW, there's a recurring meme portraying
So I guess it has been there for ages. It's good to know that I'm not the only one who wants this. |
npm is experimenting with approaches to this in some of their recent tooling, IIRC, so I'm not sure this is an area that package managers can't innovate in. Most languages only allow a single version of a package to be used at a time, process wide. Node's approach of allowing multiple versions of a dependency, possibly multiple incompatible versions, to all exist and be used in the same process is not so common, and makes the search you describe much more complex. Have you taken a shot at implementing this, or are you hoping to motivate someone else to do it? |
That approach still wastes disk space and bandwidth.
This isn't true with Rust (Cargo) and Haskell (Hackage). Rust uses semantic version (just like npm packages), which has major version indicating backward incompatibility. Haskell also has its own versioning system that support backward incompatibility. What this means is, their compiler has to pick the correct version specified by manifest files.
What would be the problem? |
Another benefit this feature would provide is implementing a package manager should become far easier. |
|
Some notes: Packages and modules are not the same and Node.js currently doesn't interpret any package metadata other than the main field (e.g. it doesn't even look at the |
They are basically
Once node add this feature (behind an experiment flag), I'm pretty sure package managers will start supporting this.
I've updated my comment, thanks for pointing this out.
Node.js doesn't have read
I've removed "multiple runtime versions (es5, es6, nodejs versions, bundlers, etc.)" part from the first comment. |
I'd say the general consensus is that even reading "main" was, in retrospect, a mistake. It's unlikely Node.js will start parsing more of package.json, or any other file. The current system works well enough; your proposal is at best a marginal improvement, worst case it's a regression because it slows down the common case. A lot of effort has been sunk in making the module loader fast. |
Node.js can hide this feature behind a flag. Even when enabled, Node.js will always try to load from |
I think you might be underestimating how many modules some apps require. :) One I work on loads over 1,400 modules at startup and it's not even that big and enterprise-y. |
An act of loading a module comprises of 3 steps: (1) resolving module path, (2) reading module file into memory, and (3) "eval"-ing content of the file. How significant can step (1) be compared to the rest? |
I will try creating a loader in form of a npm package as a proof of concept when I have time. I will not touch the Node.js repo itself. |
@KSXGitHub you may be interested in Yarn's 'Plug and Play' feature (RFC) which effectively turns Yarn's package cache into the central package store, via use of a custom resolver. |
@edmorley It is yarn-specific, and it requires changing |
what about the use case for npm link, or being able to edit files locally on disk without affecting other projects? Certainly for the simple cases you could use the package manager to install a copy in node_modules, but when the package you wish to edit is a singleton or part of a plugin ecosystem (like that of Resct, eslint, babel, etc), what happens? |
This feature does not prevent user from using |
again, though, that all seems like things the package manager, not the platform, need to address. node already has a mechanism to require from a central place, if the package manager installs there. |
That central place does not support multiple versions of the same package. |
ah, that’s a fair point. |
That's still just a packaging thing... if i The key here is that versions are tied to distribution, not loading. Node itself doesn't know what the |
Versions in Cargo (Rust) and Cabal (Haskell) are tied to loading. It is Node that is being unconventional. Node can read manifest files to learn about versions.
...unless there's gain in doing it. |
Cargo and Cabal are not the language, they are package managers. the rust compiler doesn't know or care about the version being used, it just uses whatever linking information cargo gives it when you use |
When I first used Node.js, I really liked how once I'm done with a project, I can just delete the whole directory and get rid of all the modules I installed for it in one swoop. It felt like a huge improvement compared to Python, where you can easily end up with dozens of globally installed packages that you can't remove because you don't know if some script somewhere depends on them. So your argument about disk space is a double-edged sword. Sure, you will have multiple copies of the same module if you have many projects depending on it. But I'd rather have many copies of a module that are actually used, rather than a pile of globally installed packages that might be long obsolete. |
It doesn't seem like there is broad acceptance for this proposal. I'm leaving it open for now but unless something significant happens, I'll close it out in a few days.
@KSXGitHub Enough that several people (including yours truly) invested plenty of time in making it faster. Take a look at the history of lib/module.js and src/node_file.cc; the commit logs are informative. |
|
Because you’re not requiring from the cache (also, the cache has existed for many years; it’s not new in either npm or yarn) - the cache just makes installs faster. This makes the cache always safe to delete, since it can’t possibly have any negative effect except making the next installs take longer. |
Per my previous comment, I'll go ahead and close this out. |
Problem
Projects that use Node.js likely also use npm packages, and thus contain a
node_modules
folder. Having multiple projects like this leads to having multiplenode_modules
folder which likely contain duplicated packages. This not only wastes disk space, it also wastes bandwidth and time to install these packages.(Other platforms (such as Haskell, Rust, Java) avoid this by having a centralized package repository, I was quite surprised at Node's design decision)
Description
require("pkg-name")
, if"pkg-name"
is not found inmodule.paths
, Node.js should proceed to search in a fixed location (let's call it$PREFIX/.node_package_store
until we find a better name) for a"pkg-name"
that matches criteria specified in a manifest file within the project (preferably but not necessarypackage.json
).$PREFIX/.node_package_store
is not anode_modules
and$NODE_PATH
(i.e.module.paths
) does not affect it.$PREFIX/.node_package_store
should supportmultiple runtime versions (es5, es6, nodejs versions, bundlers, etc.),multiple package versions and multiple registries.Example structure of a
.node_package_store
When use npm to install React from registry.npmjs.org
Alternatives I've considered
/node_modules
,$HOME/node_modules
and the likes: Does not support multiple versions, as a result, different projects still require different/separatednode_modules
.The text was updated successfully, but these errors were encountered: