Explained: What are Node.js modules?
Jul 5, 2017When you write Node.js applications, you could actually put all your code into one huge index.js file, no matter how large or complex your application is. The Node.js interpreter doesn’t care. But in terms of code organization, you would end up with a hard to understand and hard to debug mess quite quickly. So as a human being, you should care about how to structure your code. This is where modules come in.
You can think of Node.js modules as JavaScript libraries - a certain part of your overall codebase (for example, a collection of functions) which you want to keep together, but which you also want to keep separated from the rest of your codebase to keep things cleanly separated.
Just like we keep our socks in one drawer and our shirts in another drawer in our wardrobe - even if we combine both to create an outfit for the day - we can keep different parts of our codebase in different modules and then combine them into a coherent application.
Built-in Modules
Even if we don’t create any Node.js modules ourselves, we already have modules at our disposal because the Node.js environment provides built-in modules for us. We already encountered one of these modules in this blog when we looked at how to use the built-in WHATWG URL parser.
Within our own code file, we needed to use existing code which was declared elsewhere - in this case, the URL
class
which is part of the built-in Node.js module url
:
var URL = require('url').URL;
The require('url')
part is what gives us access to the code of the url
module. Where and how this module is defined
is completely opaque for us - all we need to know is its name - url
- and the attributes it exposes, like URL
.
Other built-in modules directly expose the attribute we need (which often are JavaScript objects). The http
module is
an example:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('Hello World!');
}).listen(8080);
Here, requiring the http
module gives us direct access to an http
object, whose methods, like createServer
, we can
then use.
The Node Beginner Book explains how to write a complete web server with Node.js
using the built-in http
module.
External Modules
The built-in modules which ship with Node.js allow to solve a lot of coding problems without reinventing the wheel for
every new application, but what really boosts Node.js programming productivity is the huge ecosystem of open source
modules provided by the Node.js community. These modules can be integrated into our codebase, too, but because they are
not built-in and don’t ship directly with each installation of Node.js, it is not enough to require
them from our own
code. We need to install the codebase containing the external module locally first, which is made very easy thanks to
NPM, the Node Package Manager.
See this blog post which describes how to use the async library for an example of how to use external modules.
Also, The Node Craftsman Book has a chapter on the details of working with NPM.
Creating your own modules
Built-in and external modules are provided by others, but nothing stops you from creating your own Node.js modules.
The following example creates a module myRandom
which provides a helper function that returns random number between 1
and 10:
File myRandom.js
:
function getRandom(min, max) {
return Math.random() * (max - min) + min;
}
exports.between1and10 = function() {
return getRandom(1, 10);
};
You would put this code into it’s own file called myRandom.js
. Because this file exists and provides attributes to the
outer world via exports
, another file index.js
can use the exported functionality:
File index.js
:
var myRandom = require('./myRandom.js');
console.log(myRandom.between1and10());
Again, require
comes into play, making the exported attributes of the local myRandom
module available - in this
case, the between1and10
function.
Note: While the module system allows to expose functionality of a module, it also allows to hide functionality which
is not needed outside of the module, simply by not exporting the functionality via exports
. Even though the index.js
file has required the myRandom.js
file, it cannot access its non-exported getRandom
function:
var myRandom = require('./myRandom.js');
console.log(myRandom.getRandom(5, 99));
will result in a TypeError: myRandom.getRandom is not a function
.
By hiding implementation details in a module and only exposing those parts which are to be used by other parts of your codebase, you can keep your codebase well organized.
Learn more about working with modules and building your own web server application with Node.js with The Node Beginner Book - the first part of this step-by-step Node.js tutorial is available for free!