Require and module.export

Node.js provides a building mechanism for modules. The way they are implemented, there is the require method which will allow you to import functionality from other modules or files, and there is also module.exports, which allows you to create modules by exporting functionality to other programs or other files.

Let's say we have two files account-service.js and utility.js.

The utility.js has some generic methods and objects which we use in many projects and applications. In this example, we will import those generic methods into account-service.js.

Here's the code of utility.js in which we expose code to account-service.js (or any other program) by assigning it to a special global module.exports:

module.exports = function(numbersToSum) {
  let sum = 0, 
    i = 0, 
    l = numbersToSum.length;
    while (i < l) {
        sum += numbersToSum[i++]
    }
    return sum
}

The main program (account-service.js) imports the utility module and executes it to find out the total balance:

const sum = require('./utility.js')

let checkingAccountBalance = 200
let savingsAccountBalance = 1000
let retirementAccountBalance = 20000

let totalBalance=sum([checkingAccountBalance, savingsAccountBalance, retirementAccountBalance] )
console.log(totalBalance)

The account-service.js can be run from the same folder where the file is located with node account-service.js. The code will import the utility.js and invoke sum(). Thus, the result will be output of the total balance.

You can have other codes in your file, but it is not important to export everything of the file. You can decide what to export, what functionality you want to give to the other files. The module.exports exports only those what is assigned to it. You can export a function, a Javascript Object, an array, or anything. Whatever you want to export is upto you.

So, the main thing to remember from this lesson whatever you are exporting is exactly the same thing that you will be importing. When you are importing something you should assign it to a variable so that you can use that variable later.

require()

require() can be used to import many different types of modules, not just for local node.js files. You can use require() to do the following:

const filesystem = require('fs') // core module
const express = require('express') // npm module
const server = require('./boot/server.js') // server.js file with a relative path down the tree
const server = require('../boot/server.js') // server.js file with a relative path up the tree
const server = require('/var/www/app/boot/server.js') // server.js file with an absolute path 
const server = require('./boot/server') // file if there's the server.js file
const routes = require('../routes') // index.js inside routes folder if there's no routes.js file
const databaseConfigs = require('./configs/database.json') // JSON file

require() with Local Files

To use require() with local files, specify the name string (the argument to require()) of the file you are trying to import. In general, start the name string with a . to specify that the file path is relative to the current folder of the node.js file or a .. to specify that the file path is relative to the parent directory of the current folder. For example, const server = require('./boot/server.js') imports a file named server.js which is in a folder named boot that is in the current folder relative to the code file in which we write require().

require() with npm or core modules/packages

To use require() with an npm or core module/package, enter the module/package name as the name string. There should not be . or .. in the name string. For example, const express = require('express') imports a package named express. The package is in the node_modules folder in the root of the project if it's an installed npm package, and in the system folder if it's a core Node module (exact location depends on your OS and how you installed Node).

require() Caching

require() caches the results based on the filename and path. Any code outside of the module.exports assignment will be run just once during the process execution. For example, the following code is a module named utility.js and it has some code outside of module.exports:

// utility.js
console.log('This will be printed just once')

module.exports = function(numbersToSum) {
  let sum = 0, 
    i = 0, 
    l = numbersToSum.length;
    while (i < l) {
        sum += numbersToSum[i++]
    }
    return sum
}

The account-service.js file uses our utility.js module:

// account-service.js
const sum = require('./utility.js')

let checkingAccountBalance = 200
let savingsAccountBalance = 1000
let retirementAccountBalance = 20000

let totalBalance=sum([checkingAccountBalance, savingsAccountBalance, retirementAccountBalance] )
console.log(totalBalance)

This is app.js which imports two files. You can also use require() to run code without assigning the result to anything.

const sum = require('./utility.js')
require('./account-service.js')

let checkingAccountBalance = 200
let savingsAccountBalance = 1000
let retirementAccountBalance = 20000

retirementAccountBalance = 40000

let totalBalance=sum([checkingAccountBalance, savingsAccountBalance, retirementAccountBalance] )
console.log(totalBalance)

In app.js when you import the module utility.js two or more times (directly and indirectly via account-service.js), the code in utility.js which prints "This will be printed just once" (it's outside the module.exports) will be run just once despite the fact that the function module.exports (which we exported) is invoked twice: once in account-service.js and the second time in app.js.

Therefore, running app.js will result in its balance being printed twice, one time in account-service and another time in app.js, but the "This will be printed just once " console log only appears once:

This will be printed just once
21200
41200

Why did the code outside module.exports run just once even though we imported the utility.js module twice (once directly and one indirectly via account-service.js)?

The reason is because Node.js will cache imports. The second time you require() the same file or a module, it will not run the code. The results of the module are already there for you to use.

Just keep this behavior in mind and as a general rule, have all the logic exported in module.exports to avoid any unwanted behavior or conflicts.

module.exports

There are several patterns which developers can use to export functionality from a module:

module.exports.name = ... or exports.name =... are used for multiple export points in a single file. They are equivalent to using module.exports = {name: ...}.

Be careful! exports = ... (without module) is not a valid module/export statement.

Here is an example -

// Common.js
exports.getKolkataPlayers = function(){
	console.log("Kolkata Players");
}
module.exports.getDelhiPlayers = function(){
	console.log("Delhi Players");
}
exports.getBangalorePlayers = function(){
	console.log("Bangalore Players");
}

// Index.js
let common = require("./common.js");
console.log(common);

// Output of Index.js
{ getKolkataPlayers: [Function],
  getDelhiPlayers: [Function],
  getBangalorePlayers: [Function]
}

As you can see, when you export multiple things from the file, they all are encapsulated within a single object. The name of the each variable is used as the key property. So the above example is equivalent to the following one -

module.exports = {
	getKolkataPlayers:function(){
		console.log("Kolkata Players");
	},
	getDelhiPlayers:function(){
		console.log("Delhi Players");
	},
	getBangalorePlayers:function(){
		console.log("Bangalore Players");
	}
}

So, regardless of the export pattern you use, module.exports will end up being an object with three greeting methods.

Core Modules

Node.js comes with batteries included. It means they are core modules that you can use and you don't have to install them with npm. They're already part of Node.js, you don't need to put them in your project folder, they are not in node_modules, they're just somewhere where your platform has been installed.

Core modules come with Node.js and don't need to be installed. Core modules provide low-level functionality and helper methods. They allow Node.js to work with the filesystem, networking, binary data, streams, spawn external processes, parse query strings, file paths and URLs, and perform other helpful tasks such as creating HTTP(S) agents/clients and servers.

Here's the list of main core modules:

There is no need to install or download core modules. To include them in your application, all you need is to use the following syntax:

const http = require('http') //replace `http` with the core module you want to use