npm chooses the first version of a package it encounters to install at the top level. Every other version is installed nested. If you have N uses of version A and one use of version B, but version B is installed first, then you get N copies of the package at version A.
What's the solution for that case though (one which requires no nesting)? I don't think a solution with no nesting exists given the current module resolution algorithm of Node.js, which allows for only a single version of a particular package to exist at a given level.
nesting can't be prevented in that case (at least with the current node require() design). It gets really bad if you have 10 packages that depend on c@1.0.0 and 10 packages that depend on c@2.0.0 -- one of them will install in the root directory and the other 10 will be duplicated. ied stores a single copy of each package@version and uses symlinks which is an improvement. Apparently yarn tried something similar but it breaks some packages (that check where they're located for example).
I could be prevented. Another project does this by using a hash of the project to all all dependencies at one level then symlinks the dependencies from hash to name so it references the correct version.
Symlink that all you want, how is it in any way whatsoever thoughtful and elegant? It's not a real solution by any stretch of the imagination. Myriads of pre-existing systems that correctly deal with this scenario existed at the time that NPM was concoted. Ignored. Considering that node is touted as a cross-platform solution, how well does version@3 deal with filesystems that don't support symlinks? I've run into this: not at all.
NPM version@3 could not be further from the ethos of "engineering." It's an outright hack, and it quickly betrays its limitations. It could have been far simpler, far more considerate of pre-existing wisdom.
no, it just installs everything it can into the top level node_modules. npm@2 would do this to a degree as well, it was just less sophisticated about it.
You can use `npm run env bin-cmd` for that. It's not as convenient as `npm exec bin-cmd` would be, but it might be easier to type than `$(npm bin)/bin-cmd`.