Node.js Internals6h estimated

The Node Module System & npm Internals

Difficulty
Importance

The problem

When code says require('lodash') or import someModule from './utils', something has to turn that string into an actual loaded file — and with potentially hundreds of installed packages nested inside each other's dependencies, resolving exactly which file that string refers to is a real, nontrivial algorithm.

Why now

Modules and bundling already established what a module is at the language level; this topic is Node's specific, concrete resolution algorithm for finding a module's actual file on disk, and package management already covered how those files got installed and organized into node_modules in the first place.

Mental model

Node's module resolution is a defined search algorithm: for a relative path, look at the exact file/directory specified; for a bare package name, walk up the directory tree checking each ancestor's node_modules folder until one contains a matching package — which is exactly why nested dependencies can each have their own, different version of the same package, resolved independently at each level of that walk.

Requires

Used in

Projects

  • Create a nested node_modules structure by hand where two packages depend on different versions of the same dependency, and confirm each resolves to its own version
  • Trace, step by step, exactly which directories Node checks when resolving require('some-package') from a file several directories deep in a project

Examples

  • require('./math') looks for exactly ./math.js (or ./math/index.js), while require('lodash') walks up through node_modules folders until one contains lodash
  • Package A depending on lodash@2 and Package B depending on lodash@4 can coexist because each gets its own nested node_modules/lodash resolved independently

Resources

Mastery checklist