modules-packagingAnswer last reviewed July 2026

Your code calls require('foo'). How does Node actually go and find that file?

Good candidates walk the lookup order, builtins, relative paths, the node_modules climb, exports versus main, and use it to explain duplicate-version bugs

What an AI-prepared candidate might say

First it checks whether it's a core module, like fs. If the string starts with ./ or ../ or /, it resolves relative to the file doing the require, so it tries the exact name, then it adds extensions, .js, .json, .node, and then it'll treat it as a directory and look for a package.json main or an index.js. Otherwise it's a bare specifier, a package name basically, and Node looks in node_modules, starting next to the requiring file and walking up the parent directories until it finds the package or hits the root. Inside the package, the package.json main field says which file is the entry point, or exports in modern packages. And results get cached, so requiring the same module twice gives you the same instance back. That caching is also why two packages can get different versions, I think, each one just finds the nearest matching node_modules.

Senior
Locked

The whole lookup order, extension probing and the directory climb included, the point where exports maps take over, and how symlink realpathing picks which copy you get.

Unlock the depth
Staff
Locked

Phantom dependencies and duplicate instances as failure classes, how to chase them down with require.resolve, and the CI guards that keep the tree honest.

Unlock the depth
Follow-up chain
Your code calls require('foo'). How does Node actually go and find that file? | NodeBook