Node Modules

Building complex applications with JavaScript isn’t a straightforward task because the language has no standard mechanism for creating libraries. CommonJS module specification suggests a way in which libraries (modules) should be written “in order to be interoperable among a class of module systems that can be both client and server side”. Node implements a similar system that makes the basic building blocks of a Node application:

Simple Modules

The most simple form of module is a single JavaScript file. In fact, every JavaScript file in a Node application is a module that wraps its code with a private context. So, unlike the web-browser environment where all JavaScript files share the same global context, in Node applications each file (module) has its own, non-shared, context. Take for example the following util.js:

The file contains one variable and two function declarations and, as you can see, the code isn’t wrapped in any way (e.g. anonymous function). This means that using util.js in a browser environment makes its content globally available, but if we use it as a Node module the code stays private and accessible only to itself. To provide access to their code, Node modules need to attach the relevant parts to a special object that is created for each module by Node’s Module system and handed to it at runtime:

When added to util.js, this line of code makes the nextSeqId() function accessible to external code as getNextId(). To use util.js we have to import it’s code and (optionally) assign it to a local variable. We then treat the local variable as an access point to the module:

On the first line, the ‘util’ module is imported by calling the special function require(), providing the module’s path and name (path isn’t always required). The result of this call is the exports object to which we attached the nextSeqId() function earlier, so when we call getNextId() we get the expected result. But what happens if we try to access currSeqId or prevSeqId()? The answer is simple – we can’t:

 

Folder Modules

What do we do when modules become big and complex? Keeping a lot of code in a single module file isn’t practical. Multiple source files organized in multiple folders with meaningful names sounds like a better idea. Also, some applications need to keep templates, data files, documentation and tests alongside the code. lumberjack is a simple logging library for Node that I created. The following picture shows its source directory structure:

 

Unlike simple modules, where the module name is the file name and code is made accessible through the exports object, folder modules need to include at least one of two special files in their root directory: either package.json, or index.js.

The first file that Node is searching for is package.json that declares the main module:

The main module is responsible for exporting the public parts of the code. In the above example, the main module is index.js that contains the following code:

This means that only four “things” are made available to the users of lumberjack (Event, Level, Logger, and LoggerFactory). It isn’t important what these “things” are. All that matters is that they are the only reachable elements of lumberjack.

If package.json isn’t found, Node automatically searches for index.js (again, under the root directory) and expects the same content  as shown in the above example with one difference – the path of the files that is passed to the required() function.

Using a folder module is the same as using a simple module:

%d bloggers like this: