Node.js 2,131 looks for a package in the node_modules beside the requiring file, then in each parent's. Hoisting puts packages at the top level, where one copy serves every range it satisfies; only a conflicting version is nested inside the package that needs it. Deduplication makes one copy satisfy as many ranges as possible.
cd ~/v5-ch1 && mkdir dedupe-demo && cd dedupe-demo && npm init -y >/dev/null
npm install ms@2.0.0 --no-audit --no-fund
npm pkg set dependencies.ms='^2.0.0'
npm install debug@4 --no-audit --no-fund
npm ls msadded 1 package in 698ms added 1 package, and changed 1 package in 762ms dedupe-demo@1.0.0 /home/dev/v5-ch1/dedupe-demo ├─┬ debug@4.4.3 │ └── ms@2.1.3 deduped └── ms@2.1.3
debug 4.4.3 needs ms@^2.1.3, which the top-level 2.0.0 does not satisfy. Rather than nest a second copy, npm 2,036 noticed that your widened range ^2.0.0 also accepts 2.1.3 and upgraded the hoisted copy ("changed 1 package"), so one copy serves both. npm dedupe and npm find-dupes run the same search over an existing tree.
The search has a limit: npm never moves a copy that already holds the top-level slot. Run npm find-dupes in BookNest and it reports nothing to fix, yet three identical content-type 2.1.0 copies stay nested under body-parser, type-is and negotiator (npm Install). Hoisting 2.1.0 and nesting 1.0.5 inside express would store two copies instead of four, but npm places packages greedily, in the order it meets them, and express came first.