Description
Steps to reproduce
Create a monorepo-style project with the following structure:
/package.json
{
"name": "monorepo",
"dependencies": {
"app": "file:./app"
}
}
/app/package.json
{
"name": "app",
"dependencies": {
"lib": "file:../lib"
}
}
/lib/package.json
{
"name": "lib"
}
There's a root package that depends on ./app
which in turn depends on ../lib
.
Now run npm install
. That will produce a node_modules
folder with two symlinks:
app -> ../app
lib -> ../lib
and a lockfile with this content:
{
"name": "monorepo",
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"app": {
"version": "file:app",
"requires": {
"lib": "file:lib"
}
},
"lib": {
"version": "file:lib"
}
}
}
Notice an important fact: the dependencies.app.requires.lib
field, with value file:lib
, contains a path relative to the root of the tree. However, in package.json
, the same dependency is specified relative to the requesting package's directory, i.e., file:../lib
. We'll later see that this difference between package-lock.json
and package.json
formats is not correctly handled.
Now, with the lockfile present, delete the node_modules
directory, and run npm install
again. This time, it runs with no node_modules
(i.e., empty currentTree
), and installs from lockfile (unlike the first run)
Expected result:
The node_modules
folder is the same as in the previous run, i.e., contains two symlinks to ../app
and ../lib
.
Actual result:
The node_modules
folder contains only the app -> ../app
symlink. The lib -> ../lib
one is not present at all. npm install
incorrectly determined that it's extraneous (not required by anyone) and prunes it (in pruneIdealTree
)
See also:
To see a real-world example in a widely used project, just check out the lerna
repo and run npm install
there. Then, running npm ls
reports a lot of missing package links:
npm ERR! missing: @lerna/cli@file:../../core/cli, required by @lerna-test/[email protected]
npm ERR! missing: @lerna/package@file:../../core/package, required by @lerna-test/[email protected]
npm ERR! missing: @lerna/get-packed@file:../get-packed, required by @lerna/[email protected]
[...]