Importing scripts in the program

Normally our application is broken down to different parts. For example, if a set of functions are used over and over, we would like them to be contained in a separate file and import that file wherever those functions are to be used.

Node.js supports this functionality natively. When you import a file inside another file, that file is called a module. Node.js uses the CommonJS module system syntax to import modules and packages.

Though ES6+ supports new module system, it is yet to be implemented in Node.

Let’s create a lib directory and place math.js file inside it. This file contains some common math functions like add and multiply . We will import this file inside calculate.js file situated in the main directory. Hence math.js is a module, since we are importing it and not executing it directly with Node.

To import a module, we need to use require function provided by the Node.js and available globally everywhere in the program. This function takes a relative or an absolute path of the module file and returns what module is exporting. Hence, we need to save it inside a variable.

// calculate.js

var math = require( './lib/math.js' ); // `.js` is optional

require() statement sometimes also called as import statement.

Now let’s take a look at math.js file. We need to provide AKA export some values to the require() function call. This is done using exports variable. This variable is also globally available everywhere.

This variable is actually an object which is empty {} at the beginning. When we import this module using require function, this is the object require() call will return.

// calculate.js

var math = require( './lib/math' ); console.log(math); // {}

Since we know that exports is an object that will be exported from the module, we can stuff it with whatever we want. As objects go, an object is a collection of key-value pairs. So let’s add some math functions to it.

// lib/math.js // add ` add ` function to `exports`

exports.add = function( num1, num2 ) {

return num1 + num2

};

From math module, we are exporting add function which returns the sum of the two numbers (arguments). Let’s see what math variable looks like.

// calculate.js

var math = require( './lib/math' ); console.log(math);

{ add: [Function] }

It shows that math variable is an object that contains add key which has a Function value. Let’s execute that function and see the result.

// calculate.js

var math = require( './lib/math' ); // add 1 + 2

var result = math.add(1, 2);

console.log( result ); // 3

What the heck is module.exports then?

I kind of skipped over this part so that you can understand module import with ease. I have a simple question, what if my math module exports only one function like add but I don’t want to export it inside an object. This is the only function my module is exporting, so I want require() call to return this function only so that I can start using it like below.

// calculate.js

var math = require( './lib/math' ); // add 1 + 2

var result = math(1, 2); // math is a function

console.log( result ); // 3

This is where module global variable comes into the picture. Like exports , module is also globally available everywhere. module is an object and it contains information about module (auto injected by Node.js in key-value pairs). The important key in this object we should know about is exports .

exports variable inside a module points to exports property on the module object, as you can prove in the below test.

// lib/math.js

console.log(exports === module.exports); // true

That means when we were setting exports.add , we were actually setting module.exports.add . So if we want our module to export only one function, we can just assign module.exports to that function.

We could say that since exports and module.exports is the same, why not just set exports to the function. The reason is how objects are handled in JavaScript. Read this answer to explore this topic in details.

// lib/math.js // export function only

module.exports = function( num1, num2 ) {

return num1 + num2

};

If your module import path is a directory, then require function will resolve index.js file inside it. Using this feature, you can have multiple . js files in a directory that contains different exports and you can import them inside index.js to exports them again from a single point.

└── lib/

├── index.js (import `math` and `graph` and export them)

├── math.js

└── graph.js

This way, the importer does not need to target individual module files in a directory. The importer can just point to index.js file.

// lib/math.js

exports.add = function( num1, num2 ) {

return num1 + num2

}; // lib/index.js

var math = require('./math');

exports.add = math.add

// calculate.js

const lib = require('./lib'); // points to './lib/index.js'

lib.add(1, 2) // 3

In Node.js, a module or a package is loaded only once (per thread or session) even when you require() them multiple times in the program. Once loaded, it will be cached by the Node for performance enhancement.

There are other tricks with CommonJS module system and sometimes we also need to be careful. Read this article to understand more about imports.