Naresh
Naresh

Reputation: 25803

How does npm3 decides to install flat vs. nested?

My project depends on angular2 beta.6 and another project that depends on angular2 beta.0.

package.json for my project

"dependencies": {
    "angular2": "2.0.0-beta.6",
    "another-project": "0.0.1"
}

package.json for another-project

"dependencies": {
    "angular2": "2.0.0-beta.0",
}

When I npm install my project, it installs angular2 twice:

  1. node_modules/angular2 (beta.6)
  2. node_modules/another-project/angular2 (beta.0)

Trying to understand how npm3 decides to nest angular2 beta.0. Is it because both are called angular2 and hence they can not both sit at the top level?

Upvotes: 7

Views: 6009

Answers (3)

wyu
wyu

Reputation: 1813

Flat dependencies were introduced in npm v3. The documentation can be found here https://docs.npmjs.com/how-npm-works/npm3.

To answer your question from the docs

However, since B v1.0 is already a top-level dep, we cannot install B v2.0 as a top level dependency. npm v3 handles this by defaulting to npm v2 behavior and nesting the new, different, module B version dependency under the module that requires it -- in this case, module C.

So order matters. The module you install first will get it's dependency on the top level. Subsequent modules will have nested dependencies.

you can run npm dedupe to remove nested module dependencies if they exist in the top level.

Upvotes: 1

Alexander O'Mara
Alexander O'Mara

Reputation: 60577

Trying to understand how npm3 decides to nest angular2 beta.0. Is it because both are called angular2 and hence they can not both sit at the top level?

Yes, this is correct. Node code require's a module by name, using code like this:

require('angular2');

Node itself is not aware of the different versions, that's the job of npm, so it just uses whatever module matches in the require path first, relying on matching directory names.

npm accommodates this by installing specific versions in directories for each module when a conflict occurs, so that the require path will include that first.

Upvotes: 3

RallionRl
RallionRl

Reputation: 31

Yes, it is because of the beta.0. Because npm has found another version of angular2 on the global level, it will install it locally.

npm3 will install globally dependencies only if there is no other versions of the dependencies on a higher level.

Here is a little example I've found :

  • [node_modules]
    • dep A v1.0
    • dep B v1.0
      • dep A v1.0 (uses root version)
    • dep C v1.0
      • dep A v2.0 (this version is different from the root version, so it will be an nested installation)

Upvotes: 3

Related Questions