Main property in package.json defines package entry point

You know your project's dependencies are installed under node_modules directory. But, when you do require('lodash'), how does Node know which file to load?

"How does Node know which file to read when loading a module?"

Module loading works in two phases

When loading a dependency, Node.js works in two phases. This is in contrast to loading a core node module with require('fs') or a local module with require('./queue/mem.js'). A dependency is loaded in two phases

  1. the right directory is looked up and
  2. the entry point within that directory is located.

Finding directory

The runtime looks up all directories that are on the path from the current file to the root of the file system. In each directory, Node checks if it contains a node_modules directory. If it does, the runtime goes inside that directory to look for a sub-directory identical to the module identifier being required. Node tries this until it finds a hit, or as a last resort, it tries few global system directories.

Locating entry point

After finding the directory, Node tries a couple of strategies to determine the entry point of the package. The entry point is the file, whose module.exports object is returned as the return value of a require()-call.

First, Node looks for a package.json file and checks if it contains a main property. It will be used to point a file inside the package directory that will be the entry point. If main property does not exist, then Node tries in order index.js, index.json and index.node.

  1. if package.json contains a main property, then use that
  2. if no main property, then try to load
    1. index.js
    2. index.json
    3. index.node

What does entry point look like for popular packages

What is done inside a package is up to the module authors. There are a couple of ways to organize the entry point to a package. Here's how some of the popular npm modules do it.

Package Main property in package.json
lodash "lodash.js"
chalk "source"
react
request "index.js"
commander "index"
moment "./moment.js"
debug "./src/index.js"
tslib "tslib.js"
fs-extra "./lib/index.js
Entry points of popular npm packages.

It can be seen that many packages define the main property, and only a few leave it to the default lookup convention.

Node doesn't wait for your database call to finish?

Node doesn't wait for your database call to finish?

Learn how asynchronous calls work and make your app run as you intended. Get short email course on asynchronicity and two chapters from Finish Your Node App.

Take Free Course