Understanding module.exports and exports in Node.js
In programming, modules are self-contained units of functionality that can be shared and reused across projects. They make our lives as developers easier, as we can use them to augment our applications with functionality that we haven't had to write ourselves. They also allow us to organize and decouple our code, leading to applications that are easier to understand, debug and maintain.
In this article, I'll examine how to work with modules in Node.js, focusing on how to export and consume them.
Different Module Formats
As JavaScript originally had no concept of modules, a variety of competing formats have emerged over time. Here's a list of the main ones to be aware of:
- The Asynchronous Module Definition (AMD) format is used in browsers and uses a
define
function to define modules. - The CommonJS (CJS) format is used in Node.js and uses
require
andmodule.exports
to define dependencies and modules. The npm ecosystem is built upon this format. - The ES Module (ESM) format. As of ES6 (ES2015), JavaScript supports a native module format. It uses an
export
keyword to export a module's public API and animport
keyword to import it. - The System.register format was designed to support ES6 modules within ES5.
- The Universal Module Definition (UMD) format can be used both in the browser and in Node.js. It's useful when a module needs to be imported by a number of different module loaders.
Please be aware that this article deals solely with the CommonJS format, the standard in Node.js. If you'd like to read into any of the other formats, I recommend this article, by SitePoint author Jurgen Van de Moere.
Requiring a Module
Node.js comes with a set of built-in modules that we can use in our code without having to install them. To do this, we need to require the module using the require
keyword and assign the result to a variable. This can then be used to invoke any methods the module exposes.
For example, to list out the contents of a directory, you can use the file system module and its readdir
method:
const fs = require('fs');
const folderPath = '/home/jim/Desktop/';
fs.readdir(folderPath, (err, files) => {
files.forEach(file => {
console.log(file);
});
});
Note that in CommonJS, modules are loaded synchronously and processed in the order they occur.
Creating and Exporting a Module
Now let's look at how to create our own module and export it for use elsewhere in our program. Start off by creating a user.js
file and adding the following:
const getName = () => {
return 'Jim';
};
exports.getName = getName;
Now create an index.js
file in the same folder and add this:
const user = require('./user');
console.log(`User: ${user.getName()}`);
Run the program using node index.js
and you should see the following output to the terminal:
User: Jim
So what has gone on here? Well, if you look at the user.js
file, you'll notice that we're defining a getName
function, then using the exports
keyword to make it available for import elsewhere. Then in the index.js
file, we're importing this function and executing it. Also notice that in the require
statement, the module name is prefixed with ./
, as it's a local file. Also note that there's no need to add the file extension.
Exporting Multiple Methods and Values
We can export multiple methods and values in the same way:
const getName = () => {
return 'Jim';
};
const getLocation = () => {
return 'Munich';
};
const dateOfBirth = '12.01.1982';
exports.getName = getName;
exports.getLocation = getLocation;
exports.dob = dateOfBirth;
And in index.js
:
const user = require('./user');
console.log(
`${user.getName()} lives in ${user.getLocation()} and was born on ${user.dob}.`
);
The code above produces this:
Jim lives in Munich and was born on 12.01.1982.
Notice how the name we give the exported dateOfBirth
variable can be anything we fancy (dob
in this case). It doesn't have to be the same as the original variable name.
Variations in Syntax
I should also mention that it's possible to export methods and values as you go, not just at the end of the file.
For example:
exports.getName = () => {
return 'Jim';
};
exports.getLocation = () => {
return 'Munich';
};
exports.dob = '12.01.1982';
And thanks to destructuring assignment, we can cherry-pick what we want to import:
const { getName, dob } = require('./user');
console.log(
`${getName()} was born on ${dob}.`
);
As you might expect, this logs:
Jim was born on 12.01.1982.
The post Understanding module.exports and exports in Node.js appeared first on SitePoint.
Comments
Post a Comment