Module in Node.js is a simple or complex functionality organized in single or multiple JavaScript files which can be reused throughout the Node.js application. Each module in Node.js has its own context, so it cannot interfere with other modules or pollute global scope. Also, each module can be placed in a separate .js file under a separate folder.
Node.js implements CommonJS modules standard. CommonJS is a group of volunteers who define JavaScript standards for web server, desktop, and console application.
Node.js Module Types
Node.js includes three types of modules:
- Core Modules
- Local Modules
- Third Party Modules
Module Basics
In the Node.js module system, each file is treated as a separate module. For example, consider a file named foo.js:
const circle = require(‘./circle.js’);
console.log(`The area of a circle of radius 4 is ${circle.area(4)}`);
On the first line, foo.js loads the module circle.js that is in the same directory as foo.js.
Here are the contents of circle.js:
const { PI } = Math;
exports.area = (r) => PI * r ** 2;
exports.circumference = (r) => 2 * PI * r;
The module circle.js has exported the functions area() and circumference(). Functions and objects are added to the root of a module by specifying additional properties on the special exports object.
Variables local to the module will be private, because the module is wrapped in a function by Node.js (see module wrapper). In this example, the variable PI is private to circle.js. The module.exports property can be assigned a new value (such as a function or object). Below, bar.js makes use of the square module, which exports a Square class:
const Square = require(‘./square.js’);
const mySquare = new Square(2);
console.log(`The area of mySquare is ${mySquare.area()}`);
The square module is defined in square.js:
// Assigning to exports will not modify module, must use module.exports
module.exports = class Square {
constructor(width) {
this.width = width;
}
area() { return this.width ** 2; } };
The module system is implemented in the require(‘module’) module.
Accessing the main module
When a file is run directly from Node.js, require.main is set to its module. That means that it is possible to determine whether a file has been run directly by testing require.main === module. For a file foo.js, this will be true if run via node foo.js, but false if run by require(‘./foo’).
Because module provides a filename property (normally equivalent to __filename), the entry point of the current application can be obtained by checking require.main.filename.
Node.js Core Modules
Node.js is a light weight framework. The core modules include bare minimum functionalities of Node.js. These core modules are compiled into its binary distribution and load automatically when Node.js process starts. However, you need to import the core module first in order to use it in your application. The following table lists some of the important core modules in Node.js.
Core Module | Description |
http | http module includes classes, methods and events to create Node.js http server. |
url | url module includes methods for URL resolution and parsing. |
querystring | querystring module includes methods to deal with query string. |
path | path module includes methods to deal with file paths. |
fs | fs module includes classes, methods, and events to work with file I/O. |
util | util module includes utility functions useful for programmers. |
Loading Core Modules – In order to use Node.js core or NPM modules, import it using require() function as
var module = require(‘module_name’);
As per above syntax, specify the module name in the require() function. The require() function will return an object, function, property or any other JavaScript type, depending on what the specified module returns.
The following example demonstrates how to use Node.js http module to create a web server.
Example: Load and Use Core http Module
var http = require(‘http’);
var server = http.createServer(function(req, res){
//write code here
});
server.listen(5000);
In the above example, require() function returns an object because http module returns its functionality as an object, you can then use its properties and methods using dot notation e.g. http.createServer(). In this way, you can load and use Node.js core modules in your application.
Cycles
When there are circular require() calls, a module might not have finished executing when it is returned. Consider this situation:
a.js:
console.log(‘a starting’);
exports.done = false;
const b = require(‘./b.js’);
console.log(‘in a, b.done = %j’, b.done);
exports.done = true;
console.log(‘a done’);
b.js:
console.log(‘b starting’);
exports.done = false;
const a = require(‘./a.js’);
console.log(‘in b, a.done = %j’, a.done);
exports.done = true;
console.log(‘b done’);
main.js:
console.log(‘main starting’);
const a = require(‘./a.js’);
const b = require(‘./b.js’);
console.log(‘in main, a.done = %j, b.done = %j’, a.done, b.done);
When main.js loads a.js, then a.js in turn loads b.js. At that point, b.js tries to load a.js. In order to prevent an infinite loop, an unfinished copy of the a.js exports object is returned to the b.js module. b.js then finishes loading, and its exports object is provided to the a.js module.
By the time main.js has loaded both modules, they’re both finished. The output of this program would thus be:
$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done = true, b.done = true
Careful planning is required to allow cyclic module dependencies to work correctly within an application.
File Modules
If the exact filename is not found, then Node.js will attempt to load the required filename with the added extensions: .js, .json, and finally .node.
.js files are interpreted as JavaScript text files, and .json files are parsed as JSON text files. .node files are interpreted as compiled addon modules loaded with process.dlopen().
A required module prefixed with ‘/’ is an absolute path to the file. For example, require(‘/home/marco/foo.js’) will load the file at /home/marco/foo.js.
A required module prefixed with ‘./’ is relative to the file calling require(). That is, circle.js must be in the same directory as foo.js for require(‘./circle’) to find it.
Without a leading ‘/’, ‘./’, or ‘../’ to indicate a file, the module must either be a core module or is loaded from a node_modules folder.
If the given path does not exist, require() will throw an Error with its code property set to ‘MODULE_NOT_FOUND’.
Folders as Modules – It is convenient to organize programs and libraries into self-contained directories, and then provide a single entry point to that library. There are three ways in which a folder may be passed to require() as an argument.
The first is to create a package.json file in the root of the folder, which specifies a main module. An example package.json file might look like this:
{ “name” : “some-library”,
“main” : “./lib/some-library.js” }
If this was in a folder at ./some-library, then require(‘./some-library’) would attempt to load ./some-library/lib/some-library.js.
This is the extent of Node.js’s awareness of package.json files.
If there is no package.json file present in the directory, or if the ‘main’ entry is missing or cannot be resolved, then Node.js will attempt to load an index.js or index.node file out of that directory. For example, if there was no package.json file in the above example, then require(‘./some-library’) would attempt to load:
- ./some-library/index.js
- ./some-library/index.node
If these attempts fail, then Node.js will report the entire module as missing with the default error:
Error: Cannot find module ‘some-library’
Loading from `node_modules` Folders – If the module identifier passed to require() is not a core module, and does not begin with ‘/’, ‘../’, or ‘./’, then Node.js starts at the parent directory of the current module, and adds /node_modules, and attempts to load the module from that location. Node.js will not append node_modules to a path already ending in node_modules.
If it is not found there, then it moves to the parent directory, and so on, until the root of the file system is reached.
For example, if the file at ‘/home/ry/projects/foo.js’ called require(‘bar.js’), then Node.js would look in the following locations, in this order:
- /home/ry/projects/node_modules/bar.js
- /home/ry/node_modules/bar.js
- /home/node_modules/bar.js
- /node_modules/bar.js
This allows programs to localize their dependencies, so that they do not clash. It is possible to require specific files or sub modules distributed with a module by including a path suffix after the module name. For instance require(‘example-module/path/to/file’) would resolve path/to/file relative to where example-module is located. The suffixed path follows the same module resolution semantics.
Loading from the global folders – If the NODE_PATH environment variable is set to a colon-delimited list of absolute paths, then Node.js will search those paths for modules if they are not found elsewhere.
On Windows, NODE_PATH is delimited by semicolons (;) instead of colons.
NODE_PATH was originally created to support loading modules from varying paths before the current module resolution algorithm was frozen.
NODE_PATH is still supported, but is less necessary now that the Node.js ecosystem has settled on a convention for locating dependent modules. Sometimes deployments that rely on NODE_PATH show surprising behavior when people are unaware that NODE_PATH must be set. Sometimes a module’s dependencies change, causing a different version (or even a different module) to be loaded as the NODE_PATH is searched.
Additionally, Node.js will search in the following list of GLOBAL_FOLDERS:
1: $HOME/.node_modules
2: $HOME/.node_libraries
3: $PREFIX/lib/node
Where $HOME is the user’s home directory, and $PREFIX is Node.js’s configured node_prefix. These are mostly for historic reasons. It is strongly encouraged to place dependencies in the local node_modules folder. These will be loaded faster, and more reliably.
Local Module – Local modules are modules created locally in your Node.js application. These modules include different functionalities of your application in separate files and folders. You can also package it and distribute it via NPM, so that Node.js community can use it. For example, if you need to connect to MongoDB and fetch data then you can create a module for it, which can be reused in your application.
Writing Simple Module – Let’s write simple logging module which logs the information, warning or error to the console. In Node.js, module should be placed in a separate JavaScript file. So, create a Log.js file and write the following code in it.
Log.js
var log = {
info: function (info) {
console.log(‘Info: ‘ + info);
},
warning:function (warning) {
console.log(‘Warning: ‘ + warning);
},
error:function (error) {
console.log(‘Error: ‘ + error);
}
};
module.exports = log
In the above example of logging module, we have created an object with three functions – info(), warning() and error(). At the end, we have assigned this object to module.exports. The module.exports in the above example exposes a log object as a module.
The module.exports is a special object which is included in every JS file in the Node.js application by default. Use module.exports or exports to expose a function, object or variable as a module in Node.js.
Now, let’s see how to use the above logging module in our application.
Loading Local Module – To use local modules in your application, you need to load it using require() function in the same way as core module. However, you need to specify the path of JavaScript file of the module.
The following example demonstrates how to use the above logging module contained in Log.js.
app.js
var myLogModule = require(‘./Log.js’);
myLogModule.info(‘Node.js started’);
In the above example, app.js is using log module. First, it loads the logging module using require() function and specified path where logging module is stored. Logging module is contained in Log.js file in the root folder. So, we have specified the path ‘./Log.js’ in the require() function. The ‘.’ denotes a root folder.
The require() function returns a log object because logging module exposes an object in Log.js using module.exports. So now you can use logging module as an object and call any of its function using dot notation e.g myLogModule.info() or myLogModule.warning() or myLogModule.error()
Run the above example using command prompt (in Windows) as shown below.
C:\> node app.js
Info: Node.js started
Thus, you can create a local module using module.exports and use it in your application.
HTTP Module
The HTTP core module is a key module to Node networking.
It has following properties
- METHODS
- STATUS_CODES
- globalAgent
It has following methods
- createServer()
- request()
- get()
It has following classes
- Agent
- ClientRequest
- Server
- ServerResponse
- IncomingMessage
It can be included using – const http = require(‘http’)
The module provides some properties and methods, and some classes.
http.METHODS – This property lists all the HTTP methods supported:
> require(‘http’).METHODS
[ ‘ACL’,‘BIND’,
‘CHECKOUT’,
‘CONNECT’,
‘COPY’,
‘DELETE’,
‘GET’,
‘HEAD’,
‘LINK’,
‘LOCK’,
‘M-SEARCH’,
‘MERGE’,
‘MKACTIVITY’,
‘MKCALENDAR’,
‘MKCOL’,
‘MOVE’,
‘NOTIFY’,
‘OPTIONS’,
‘PATCH’,
‘POST’,
‘PROPFIND’,
‘PROPPATCH’,
‘PURGE’,
‘PUT’,
‘REBIND’,
‘REPORT’,
‘SEARCH’,
‘SUBSCRIBE’,
‘TRACE’,
‘UNBIND’,
‘UNLINK’,
‘UNLOCK’,
‘UNSUBSCRIBE’ ]
http.STATUS_CODES – This property lists all the HTTP status codes and their description:
> require(‘http’).STATUS_CODES
{ ‘100’: ‘Continue’,
‘101’: ‘Switching Protocols’,
‘102’: ‘Processing’,
‘200’: ‘OK’,
‘201’: ‘Created’,
‘202’: ‘Accepted’,
‘203’: ‘Non-Authoritative Information’,
‘204’: ‘No Content’,
‘205’: ‘Reset Content’,
‘206’: ‘Partial Content’,
‘207’: ‘Multi-Status’,
‘208’: ‘Already Reported’,
‘226’: ‘IM Used’,
‘300’: ‘Multiple Choices’,
‘301’: ‘Moved Permanently’,
‘302’: ‘Found’,
‘303’: ‘See Other’,
‘304’: ‘Not Modified’,
‘305’: ‘Use Proxy’,
‘307’: ‘Temporary Redirect’,
‘308’: ‘Permanent Redirect’,
‘400’: ‘Bad Request’,
‘401’: ‘Unauthorized’,
‘402’: ‘Payment Required’,
‘403’: ‘Forbidden’,
‘404’: ‘Not Found’,
‘405’: ‘Method Not Allowed’,
‘406’: ‘Not Acceptable’,
‘407’: ‘Proxy Authentication Required’,
‘408’: ‘Request Timeout’,
‘409’: ‘Conflict’,
‘410’: ‘Gone’,
‘411’: ‘Length Required’,
‘412’: ‘Precondition Failed’,
‘413’: ‘Payload Too Large’,
‘414’: ‘URI Too Long’,
‘415’: ‘Unsupported Media Type’,
‘416’: ‘Range Not Satisfiable’,
‘417’: ‘Expectation Failed’,
‘418’: ‘I\’m a teapot’,
‘421’: ‘Misdirected Request’,
‘422’: ‘Unprocessable Entity’,
‘423’: ‘Locked’,
‘424’: ‘Failed Dependency’,
‘425’: ‘Unordered Collection’,
‘426’: ‘Upgrade Required’,
‘428’: ‘Precondition Required’,
‘429’: ‘Too Many Requests’,
‘431’: ‘Request Header Fields Too Large’,
‘451’: ‘Unavailable For Legal Reasons’,
‘500’: ‘Internal Server Error’,
‘501’: ‘Not Implemented’,
‘502’: ‘Bad Gateway’,
‘503’: ‘Service Unavailable’,
‘504’: ‘Gateway Timeout’,
‘505’: ‘HTTP Version Not Supported’,
‘506’: ‘Variant Also Negotiates’,
‘507’: ‘Insufficient Storage’,
‘508’: ‘Loop Detected’,
‘509’: ‘Bandwidth Limit Exceeded’,
‘510’: ‘Not Extended’,
‘511’: ‘Network Authentication Required’ }
http.globalAgent – Points to the global instance of the Agent object, which is an instance of the http.Agent class. It’s used to manage connections persistance and reuse for HTTP clients, and it’s a key component of Node HTTP networking.
http.createServer()– It returns a new instance of the http.Server class.
Usage:
const server = http.createServer((req, res) => {
//handle every single request with this callback
})
http.request()– Makes an HTTP request to a server, creating an instance of the http.ClientRequest class.
http.get() – Similar to http.request(), but automatically sets the HTTP method to GET, and calls req.end() automatically.
Classes
The HTTP module provides 5 classes:
- Agent
- ClientRequest
- Server
- ServerResponse
- IncomingMessage
http.Agent – Node creates a global instance of the http.Agent class to manage connections persistance and reuse for HTTP clients, a key component of Node HTTP networking. This object makes sure that every request made to a server is queued and a single socket is reused. It also maintains a pool of sockets. This is key for performance reasons.
http.ClientRequest – An http.ClientRequest object is created when http.request() or http.get() is called. When a response is received, the response event is called with the response, with an http.IncomingMessage instance as argument.
The returned data of a response can be read in 2 ways:
- you can call the response.read() method
- in the response event handler you can setup an event listener for the data event, so you can listen for the data streamed into.
http.Server
This class is commonly instantiated and returned when creating a new server using http.createServer().
Once you have a server object, you have access to its methods:
- close() stops the server from accepting new connections
- listen() starts the HTTP server and listens for connections
http.ServerResponse – Created by an http.Server and passed as the second parameter to the request event it fires. Commonly known and used in code as res:
const server = http.createServer((req, res) => {
//res is an http.ServerResponse object
})
The method you’ll always call in the handler is end(), which closes the response, the message is complete and the server can send it to the client. It must be called on each response.
These methods are used to interact with HTTP headers:
- getHeaderNames() get the list of the names of the HTTP headers already set
- getHeaders() get a copy of the HTTP headers already set
- setHeader(‘headername’, value) sets an HTTP header value
- getHeader(‘headername’) gets an HTTP header already set
- removeHeader(‘headername’) removes an HTTP header already set
- hasHeader(‘headername’) return true if the response has that header set
- headersSent() return true if the headers have already been sent to the client
After processing the headers you can send them to the client by calling response.writeHead(), which accepts the statusCode as the first parameter, the optional status message, and the headers object.
To send data to the client in the response body, you use write(). It will send buffered data to the HTTP response stream.
If the headers were not sent yet using response.writeHead(), it will send the headers first, with the status code and message that’s set in the request, which you can edit by setting the statusCode and statusMessage properties values:
response.statusCode = 500
response.statusMessage = ‘Internal Server Error’
http.IncomingMessage – An http.IncomingMessage object is created by:
- Server when listening to the request event
- ClientRequest when listening to the response event
It can be used to access the response:
- status using its statusCode and statusMessage methods
- headers using its headers method or rawHeaders
- HTTP method using its method
- HTTP version using the httpVersion method
- URL using the url method
- underlying socket using the socket method
The data is accessed using streams, since http.IncomingMessage implements the Readable Stream interface.
Add an HTTP Header – If the response from the HTTP server is supposed to be displayed as HTML, you should include an HTTP header with the correct content type:
Example
var http = require(‘http’);
http.createServer(function (req, res) {
res.writeHead(200, {‘Content-Type’: ‘text/html’});
res.write(‘Hello World!’);
res.end();
}).listen(8080);
The first argument of the res.writeHead() method is the status code, 200 means that all is OK, the second argument is an object containing the response headers.
Read the Query String – The function passed into the http.createServer() has a req argument that represents the request from the client, as an object (http.IncomingMessage object). This object has a property called “url” which holds the part of the url that comes after the domain name:
demo_http_url.js
var http = require(‘http’);
http.createServer(function (req, res) {
res.writeHead(200, {‘Content-Type’: ‘text/html’});
res.write(req.url);
res.end();
}).listen(8080);
Save the code above in a file called “demo_http_url.js” and initiate the file:
Initiate demo_http_url.js:
C:\Users\Your Name>node demo_http_url.js
If you have followed the same steps on your computer, you should see two different results when opening these two addresses: http://localhost:8080/summer , will produce this result: /summer
http://localhost:8080/winter , will produce this result: /winter
Split the Query String
There are built-in modules to easily split the query string into readable parts, such as the URL module.
Example to split the query string into readable parts:
var http = require(‘http’);
var url = require(‘url’);
http.createServer(function (req, res) {
res.writeHead(200, {‘Content-Type’: ‘text/html’});
var q = url.parse(req.url, true).query;
var txt = q.year + ” ” + q.month;
res.end(txt);
}).listen(8080);
Save the code above in a file called “demo_querystring.js” and initiate the file:
Initiate demo_querystring.js:
C:\Users\Your Name>node demo_querystring.js
The address: http://localhost:8080/?year=2017&month=July , will produce this result: 2017 July
The module wrapper
Before a module’s code is executed, Node.js will wrap it with a function wrapper that looks like the following:
(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
});
By doing this, Node.js achieves a few things:
- It keeps top-level variables (defined with var, const or let) scoped to the module rather than the global object.
- It helps to provide some global-looking variables that are actually specific to the module, such as:
- The module and exports objects that the implementor can use to export values from the module.
- The convenience variables __filename and __dirname, containing the module’s absolute filename and directory path.
__dirname – Added in: v0.1.27. It is <string>
The directory name of the current module. This is the same as the path.dirname() of the __filename. Example: running node example.js from /Users/mjr
console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr
__filename – Added in: v0.0.1 It is <string>
The file name of the current module. This is the current module file’s absolute path with symlinks resolved. For a main program this is not necessarily the same as the file name used in the command line.
Examples:
Running node example.js from /Users/mjr
console.log(__filename);
// Prints: /Users/mjr/example.js
console.log(__dirname);
// Prints: /Users/mjr
Given two modules: a and b, where b is a dependency of a and there is a directory structure of:
- /Users/mjr/app/a.js
- /Users/mjr/app/node_modules/b/b.js
References to __filename within b.js will return /Users/mjr/app/node_modules/b/b.js while references to __filename within a.js will return /Users/mjr/app/a.js.
exports – Added in: v0.1.12 It is <Object>. A reference to the module.exports that is shorter to type.
module – Added in: v0.1.16 It is <module>. A reference to the current module. In particular, module.exports is used for defining what a module exports and makes available through require().
require(id) – Added in: v0.1.13 It is id <string> module name or path. It returns, <any> exported module content. Used to import modules, JSON, and local files. Modules can be imported from node_modules. Local modules and JSON files can be imported using a relative path (e.g. ./, ./foo, ./bar/baz, ../foo) that will be resolved against the directory named by __dirname (if defined) or the current working directory.
// Importing a local module:
const myLocalModule = require(‘./path/myLocalModule’);
// Importing a JSON file:
const jsonData = require(‘./path/filename.json’);
// Importing a module from node_modules or Node.js built-in module:
const crypto = require(‘crypto’);
require.cache – Added in: v0.3.0 It is <Object>. Modules are cached in this object when they are required. By deleting a key value from this object, the next require will reload the module. Note that this does not apply to native addons, for which reloading will result in an error.
require.main – Added in: v0.1.17 It is <module>. The Module object representing the entry script loaded when the Node.js process launched. See “Accessing the main module”. In entry.js script:
console.log(require.main);
node entry.js
Module {
id: ‘.’,
exports: {},
parent: null,
filename: ‘/absolute/path/to/entry.js’,
loaded: false,
children: [],
paths:
[ ‘/absolute/path/to/node_modules’,‘/absolute/path/node_modules’,
‘/absolute/node_modules’,
‘/node_modules’ ] }
require.resolve(request[, options]) – Updated in v8.9.0. The request is <string> for module path to resolve and options is <Object>, as
- paths <string[]> Paths to resolve module location from. If present, these paths are used instead of the default resolution paths, with the exception of GLOBAL_FOLDERS like $HOME/.node_modules, which are always included. Note that each of these paths is used as a starting point for the module resolution algorithm, meaning that the node_modules hierarchy is checked from this location.
It returns <string>. Use the internal require() machinery to look up the location of a module, but rather than loading the module, just return the resolved filename.
require.resolve.paths(request) – Added in: v8.9.0
- request <string> The module path whose lookup paths are being retrieved.
- Returns: <string[]> | <null>
It returns an array containing the paths searched during resolution of request or null if the request string references a core module, for example http or fs.
The `module` Object
Added in: v0.1.16. It is <Object>. In each module, the module free variable is a reference to the object representing the current module. For convenience, module.exports is also accessible via the exports module-global. module is not actually a global but rather local to each module.
module.children – Added in: v0.1.16 It is <module[]>. The module objects required for the first time by this one.
module.exports – Added in: v0.1.16 It is <Object>. The module.exports object is created by the Module system. Sometimes this is not acceptable; many want their module to be an instance of some class. To do this, assign the desired export object to module.exports. Note that assigning the desired object to exports will simply rebind the local exports variable, which is probably not what is desired.
For example, suppose we were making a module called a.js:
const EventEmitter = require(‘events’);
module.exports = new EventEmitter();
// Do some work, and after some time emit the ‘ready’ event from the module itself.
setTimeout(() => {
module.exports.emit(‘ready’);
}, 1000);
Then in another file we could do:
const a = require(‘./a’);
a.on(‘ready’, () => {
console.log(‘module “a” is ready’);
});
Note that assignment to module.exports must be done immediately. It cannot be done in any callbacks. This does not work:
x.js:
setTimeout(() => {
module.exports = { a: ‘hello’ };
}, 0);
y.js:
const x = require(‘./x’);
console.log(x.a);
exports shortcut – Added in: v0.1.16. The exports variable is available within a module’s file-level scope, and is assigned the value of module.exports before the module is evaluated.
It allows a shortcut, so that module.exports.f = … can be written more succinctly as exports.f = …. However, be aware that like any variable, if a new value is assigned to exports, it is no longer bound to module.exports:
module.exports.hello = true; // Exported from require of module
exports = { hello: false }; // Not exported, only available in the module
When the module.exports property is being completely replaced by a new object, it is common to also reassign exports:
module.exports = exports = function Constructor() {
// … etc.
};
To illustrate the behavior, imagine this hypothetical implementation of require(), which is quite similar to what is actually done by require():
function require(/* … */) {
const module = { exports: {} };
((module, exports) => {
// Module code here. In this example, define a function.
function someFunc() {}
exports = someFunc;
// At this point, exports is no longer a shortcut to module.exports, and
// this module will still export an empty default object.
module.exports = someFunc;
// At this point, the module will now export someFunc, instead of the
// default object.
})(module, module.exports);
return module.exports;
}
The module.exports or exports is a special object which is included in every JS file in the Node.js application by default. module is a variable that represents current module and exports is an object that will be exposed as a module. So, whatever you assign to module.exports or exports, will be exposed as a module.
Let’s see how to expose different types as a module using module.exports.
Export Literals – As mentioned above, exports is an object. So it exposes whatever you assigned to it as a module. For example, if you assign a string literal then it will expose that string literal as a module. The following example exposes simple string message as a module in Message.js.
Message.js
module.exports = ‘Hello world’;
//or
exports = ‘Hello world’;
Now, import this message module and use it as shown below.
app.js
var msg = require(‘./Messages.js’);
console.log(msg);
Run the above example and see the result as shown below.
C:\> node app.js
Hello World
You must specify ‘./’ as a path of root folder to import a local module. However, you do not need to specify path to import Node.js core module or NPM module in the require() function.
Export Object – exports is an object. So, you can attach properties or methods to it. The following example exposes an object with a string property in Message.js file.
Message.js
exports.SimpleMessage = ‘Hello world’;
//or
module.exports.SimpleMessage = ‘Hello world’;
In the above example, we have attached a property “SimpleMessage” to the exports object. Now, import and use this module as shown below.
app.js
var msg = require(‘./Messages.js’);
console.log(msg.SimpleMessage);
In the above example, require() function will return an object { SimpleMessage : ‘Hello World’} and assign it to the msg variable. So, now you can use msg.SimpleMessage.
Run the above example by writing node app.js in the command prompt and the output is as
C:\> node app.js
Hello World
The same way as above, you can expose an object with function. The following example exposes an object with log function as a module.
Log.js
module.exports.log = function (msg) {
console.log(msg);
};
The above module will expose an object- { log : function(msg){ console.log(msg); } } . Use the above module as shown below.
app.js
var msg = require(‘./Log.js’);
msg.log(‘Hello World’);
Run and see the output in command prompt as shown below.
C:\> node app.js
Hello World
You can also attach an object to module.exports as shown below.
data.js
module.exports = {
firstName: ‘James’,
lastName: ‘Bond’
}
app.js
var person = require(‘./data.js’);
console.log(person.firstName + ‘ ‘ + person.lastName);
Run the above example and see the result as shown below.
C:\> node app.js
James Bond
Export Function – You can attach an anonymous function to exports object as shown below.
Log.js
module.exports = function (msg) {
console.log(msg);
};
Now, you can use the above module as below.
app.js
var msg = require(‘./Log.js’);
msg(‘Hello World’);
The msg variable becomes function expression in the above example. So, you can invoke the function using parenthesis (). Run the above example and see the output as shown below.
C:\> node app.js
Hello World
Export function as a class – In the JavaScript, a function can be treated like a class. The following example exposes a function which can be used like a class.
Person.js
module.exports = function (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = function () {
return this.firstName + ‘ ‘ + this.lastName;
}
}
The above module can be used as shown below.
app.js
var person = require(‘./Person.js’);
var person1 = new person(‘James’, ‘Bond’);
console.log(person1.fullName());
As you can see, we have created a person object using new keyword. Run the above example as below.
C:\> node app.js
James Bond
In this way, you can export and import a local module created in a separate file under root folder.
Node.js also allows you to create modules in sub folders. Let’s see how to load module from sub folders.
Load Module from Separate Folder – Use the full path of a module file where you have exported it using module.exports. For example, if log module in the log.js is stored under “utility” folder under the root folder of your application then import it as shown below.
app.js
var log = require(‘./utility/log.js’);
In the above example, . is for root folder and then specify exact path of your module file. Node.js also allows us to specify the path to the folder without specifying file name. For example, you can specify only utility folder without specifying log.js as shown below.
app.js
var log = require(‘./utility’);
In the above example, Node will search for a package definition file called package.json inside utility folder. This is because Node assumes that this folder is a package and will try to look for a package definition. The package.json file should be in a module directory. The package.json under utility folder specifies the file name using “main” key as below.
./utility/package.json
{
“name” : “log”,
“main” : “./log.js”
}
Now, Node.js will find log.js file using main entry in package.json and import it. If package.json file does not exist then it will look for index.js file as a module file by default.
module.filename – Added in: v0.1.16 It is <string>. The fully resolved filename of the module.
module.id – Added in: v0.1.16 It is <string>. The identifier for the module. Typically this is the fully resolved filename.
module.loaded – Added in: v0.1.16 It is <boolean>. Whether or not the module is done loading, or is in the process of loading.
module.parent – Added in: v0.1.16 It is <module>. The module that first required this one.
module.paths – Added in: v0.4.0 It is <string[]>. The search paths for the module.
module.require(id) – Added in: v0.5.1
- id <string>
- Returns: <any> exported module content
The module.require() method provides a way to load a module as if require() was called from the original module. In order to do this, it is necessary to get a reference to the module object. Since require() returns the module.exports, and the module is typically only available within a specific module’s code, it must be explicitly exported in order to be used.
The `Module` Object
Added in: v0.3.7 It is <Object>. Provides general utility methods when interacting with instances of Module — the module variable often seen in file modules. Accessed via require(‘module’).
module.builtinModules – Added in: v9.3.0. It is <string[]>. A list of the names of all modules provided by Node.js. Can be used to verify if a module is maintained by a third party or not. Note that module in this context isn’t the same object that’s provided by the module wrapper. To access it, require the Module module:
const builtin = require(‘module’).builtinModules;
module.createRequireFromPath(filename) – Added in: v10.12.0
- filename <string> Filename to be used to construct the relative require function.
- Returns: <require> Require function
const { createRequireFromPath } = require(‘module’);
const requireUtil = createRequireFromPath(‘../src/utils’);
// require `../src/utils/some-tool`
requireUtil(‘./some-tool’);