How NodeJs require module actually works?

Biplap Bhattarai
3 min readApr 25, 2021

--

Requiring a Module in NodeJs seems like a simple concept, you require a module using require(“module_name”) function and start working with it.

Modularity is the concept NodeJs is based on. Each module in Node has its own scope. A module cannot directly access things defined in another module unless it chooses to expose them. To expose things from a module, the module must be assigned to exports or module.exports. For a module to access another module’s exports or module.exports, it must use require().

When we require a module Node goes through following steps:

  1. Resolving, to find the absolute path of module
  2. Loading, to determine and load the content of file at resolved module.
  3. Wrapping, give every module private scope. And what makes require local to every module.
  4. Evaluating, what VM does with code.
  5. Caching, when module required again, the whole steps doesn’t have to be repeated.

Creating a Module

If my current path is

~/test_project $ pwd
/home/bhattaraib58/test_project/

Let’s create a Module called is_fibonacci_number in node_modules folder:

// is_fibonacci_number.js
console.log(“In ‘/home/bhattaraib58/test_project/node_modules’ “)

Requiring the module in “test_project/index.js”:

require(“is_fibonacci_number”)

What the require statement does is that it starts searching for is_fibonacci_number from the base project directory in the path:

‘/home/bhattaraib58/test_project/node_modules’

and the console gives:

~/test_project $ node index.js
In ‘/home/bhattaraib58/test_project/node_modules’

If we create a modified module in ‘/home/node_modules’,

/* /home/node_modules/is_fibonacci_number.js */

console.log(“In ‘/home/node_modules’ ”)

Requiring the module in “/home/bhattaraib58/test_project/index.js”:

require(“is_fibonacci_number”)

Still gives us the same console from is_fibonacci_number module in test_project/node_modules

~/test_project $ node index.js
In ‘/home/bhattaraib58/test_project/node_modules’

Since NodeJs resolved the Module in the top-level project directory, it stops looking for the module elsewhere.

Let’s remove the module

~/test_project $ cd node_modules
~/test_project/node_modules $ rm is_fibonacci_number.js

Let’s Run again console gives:

~/test_project $ node index.js
In ‘/home/node_modules’

The log is different this time, NodeJs has resolved the is_fibonacci_number module from 2 level above from current project directory this time.

Viewing NodeJs Module Import Priority Paths

Let’s see how NodeJs resolved the modules:

~/test_project $ node
> console.log(module)
Module {
id: ‘<repl>’,
path: ‘.’,
exports: {},
parent: undefined,
filename: null,
loaded: false,
children: [],
paths: [
‘/home/bhattaraib58/test_project/repl/node_modules’,
‘/home/bhattaraib58/test_project/node_modules’,
‘/home/bhattaraib58/node_modules’,
‘/home/node_modules’,
‘/node_modules’,
‘/home/bhattaraib58/.node_modules’,
‘/home/bhattaraib58/.node_libraries’,
‘/home/bhattaraib58/.nvm/versions/node/v14.15.1/lib/node’
]

}

In module, we can see the paths array, which helps us to see where the required modules will be imported from. Then from the current directory until base folder, Node checks for node_modules folder in each level. The closer the module is to import path, faster the module import is resolved.

The paths:

‘/home/bhattaraib58/.node_modules’,
‘/home/bhattaraib58/.node_libraries’,
‘/home/bhattaraib58/.nvm/versions/node/v14.15.1/lib/node’

is used for historic reasons and is no longer recommended to be used.

If Module is not found in all of these paths, Node gives us error unable to resolve the module.

> require(“is_fibonacci_number”)
Uncaught Error: Cannot find module ‘is_fibonacci_number’
Require stack:
- <repl>
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
at Function.Module._load (internal/modules/cjs/loader.js:725:27)
at Module.require (internal/modules/cjs/loader.js:952:19)
at require (internal/modules/cjs/helpers.js:88:18) {
code: ‘MODULE_NOT_FOUND’,
requireStack: [ ‘<repl>’ ]
}

JSON and C++ Addons Import:

You can also import JSON and C++ addons node in NodeJs.

When we require a Module NodeJs always try to import module in the following Order:

require(“module”)

  1. module.js
  2. module.json // JSON data file
  3. module.node // C++ Addons File (Create C++ Addons: https://nodejs.org/dist/latest-v14.x/docs/api/addons.html#addons_hello_world

--

--