Skip to content
tezvyn:
Menu

Diamond dependencies and nested node_modules

Source: interviewHardHow cards are made

Summary

understanding npm's nested install layout.

Key points

npm hoists one version to the top and nests the conflicting version under the dependent package; both coexist on disk.

What's really being asked

This examines whether you understand npm's deduplication and nesting strategy and the subtle bugs that arise when multiple copies of a supposedly single library load at once.

The full answer

Modern npm uses a flat install where it hoists one version of each package to the top-level node_modules whenever it can satisfy the most consumers. When two dependencies need incompatible major versions, npm cannot hoist both, so it places one at the top and nests the other copy inside the requiring package's own node_modules directory. Node's resolution then walks up from each module, so lib-A finds its lodash 3 and lib-B finds its lodash 4. Both physically exist, the build works, and each consumer is happy. The trouble is duplication: the bundle or install is larger, and crucially any library that assumes it is a singleton breaks. If two copies of such a library load, they hold separate internal state, instanceof checks against the other copy's classes fail, and shared registries or contexts silently diverge.

The mistakes people make

Saying npm can only ever install one version of a package, that the diamond always causes an install error, or ignoring the singleton hazard entirely. Another mistake is assuming hoisting is deterministic regardless of install order.

What usually comes next

How peerDependencies prevent duplicate singletons, why instanceof fails across copies, how bundlers dedupe, and how pnpm's symlinked store changes this picture.

A concrete example

A UI app pulls in two component libraries that each depend on a different major of a shared context library. npm hoists one and nests the other, so two copies of that context library run. A provider rendered with copy one is invisible to a consumer reading copy two, because they reference different module instances, and instanceof checks across them return false. The fix is declaring the context library as a peerDependency so the host app supplies one shared copy.

Interview question

Why can two installed major versions of the same library cause instanceof checks to fail across packages?

  • a.The older version overwrites the newer version's prototypes
  • b.Each copy is a distinct module instance with its own classes, so cross-copy instanceof returns falseCorrect
  • c.instanceof never works in Node with hoisted dependencies
  • d.npm strips prototype chains during install
Why?

Two physical copies are separate module instances with separate class identities, so an object from one copy is not an instance of the other copy's class. npm does not strip prototypes.

Just read this? Test yourself on what you have been reading.

Read the original → npm.github.io

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on nodejs — each one lists the topics its interview covers.

See open roles