-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
[BUG] Installing a package globally also installs its peerDependencies even if they are already available globally #7057
Comments
This is expected since global modules can’t be required. |
@ljharb they can and they are. The proof in the description of the issue: typedoc themes require typedoc successfully when both are installed globally. You are confusing non-global modules - that can't require global modules - and global modules that can. I want to make clear that node.js has no specification at all that prevents global modules from being required. The specification of the So, it is totally wrong to say "global modules can’t be required". That said, to keep it simple, the rest of this comment assumes that Node.js walks the filesystem up to the root when looking for a module to load. So, yes, you are right, global modules are not considered when a module is required from a non global package. /home/me/my-local-package/node_modules
/home/me/node_modules
/home/node_modules
/node_modules In this case global modules are not considered by the resolution algorithm. But global modules are installed in the global modules directory. So walking up the filesystem eventually ends up in the root of the global module directory, allowing Node.js to actually find the required module. /home/me/global-modules/a-global-package/node_modules
/home/me/global-modules/node_modules
/home/me/node_modules
/home/node_modules
/node_modules Here the global modules are considered by Node.js. So:
|
If true that’s still surprising to me, but fair enough. |
This is intentional. There is no overarching $ ls (npm prefix -g)/lib
node_modules/ Therefore npm can't treat it like a package, specifically it can't know about other packages that are installed alongside each other. Each package installed globally is done as a discrete unit. Allowing the fact that global package could require each other to be relied on would mean that npm could remove a peer of an existing package if asked. TLDR the global package namespace is not a single package namespace. Each globally installed package is treated as its own discrete installation and packages that happened to rely on cross-requiring across the global namespace may experience unexpected results. |
There is also the fact that when one is installing into the global namespace there is no way to know what other packages may be requiring into it. The current npm contract is that There is no way to guarantee that a global install could keep this project with non-global packages that require into the global namespace |
@wraithgar thanks a lot. Just to be sure that I understood perfectly: peer dependencies are automatically installed only when a package is installed globally, and must be installed manually when a package is installed locally, right? Ot is it automatic in both cases? If it is automatic in both cases, what is the point of having https://docs.npmjs.com/cli/v7/configuring-npm/package-json#peerdependenciesmeta
About the issue with typedoc I discussed with the team and we will have our pipeline install typedoc and its themes locally (instead of globally) after |
It's not always fully solvable by a computer (think P=NP hard); it's always best to have peer deps explicitly installed. Certainly in general, installing things locally is always better than globally, so that's the best outcome. |
The docs for
It looks like the language in |
Good |
Is there an existing issue for this?
This issue exists in the latest npm version
Current Behavior
When installing a package globally, its peer dependencies are also always installed in its own
node_modules
directory even when these peer dependencies are already installed globally.Expected Behavior
I expect that the peer dependencies available globally are not installed globally twice when they are the same version, just like
npm
behaves when installing locally.Having multiple versions of the same global dependency creates some issues with typedoc (probably among some other tools) where typedoc ends up installed twice:
node_modules
directoryObviously, when executing the typedoc binary to build a documentation, the executed instance of typedoc is not the one that is required by the theme, leading to the infamous error:
To confirm that there is no need to install "locally" peer dependencies that are already installed globally, I deleted the
/home/ericmorand/.nvm/versions/node/v18.19.0/lib/node_modules/typedoc-material-theme/node_modules/typedoc
directory, rerun the command and everything went fine.Which is to be expected: the theme eventually requires
typedoc
which is then resolved to the package installed one level above the theme, as per the resolution rule of node:https://nodejs.org/api/modules.html#loading-from-node_modules-folders
Workarounds:
node_modules/typedoc
directory which may be challenging in a build system where we don't necessarily control where global packages are locatednpm
respect the rule of not installing twice the same dependency - but it means all our projects need to be reworked because none of them include typedoc or its themes: our build system is responsible for the documentation building and it is where we enforce some common typedoc themes and settings for all our products, for consistency and convenience--legacy-peer-deps
flag which is the best solution we found - it is simple and it works :partySteps To Reproduce
npm i -g typedoc
npm i -g typedoc-material-theme
node_modules
directory: you'll findtypedoc
installed under both the globalnode_modules
directory and undernode_modules/typedoc-material-theme/node_modules
Environment
The text was updated successfully, but these errors were encountered: