Overview of Modules in Node.js

Node.js is an open source, server-side runtime environment which runs on various platforms like Windows, Linux, Unix and other operating systems. Node.js is built on JavaScript engine and provides ability to build scalable applications. The runtime environment is eventdriven and provides asynchronous programming which is memory efficient. Node.js is useful in generating dynamic page contents as it eliminates the need for the wait to open and close files and continues with the next request. We can also use Node.js to modify data in our database. 

In other languages, it’s usually better to structure our application code and break it into small pieces. However, in ode.js, we can write all our application code in one index.js file, irrespective of the complexity of our application, and the node.js interpreter will not cause issues. But, if we have very complex application, it would be better to divide our application code into small modules and then combine them into a cohesive application. 

Node.js modules are the different functions which can be reused time and time again. They can be organized into single or multiple JavaScript files in the same or different folders. Each file is treated as single module. They can also be considered as JavaScript libraries. Every module has its own context and does not interfere in the working of another module. Together, these modules help to run the application.  

Before we deep dive into types of modules, let’s take a quick example of creating a simple module.  

The above module will calculate the average of two numbers and display the output. 

When we install node.js, several lightweight modules are automatically createdwhich provide bare minimum functionalities.  These modules are compiled into the node.js binary. They are also referred to as core modules and located in the lib folder. Below are few of the built-in modules in node.js   

These modules are used in our application code as reference. The code of these modules are not part of our program as they work as libraries. They are always loaded if their identifies is passed to require().  

Let’s see an example:

Here require(‘url’) is what gives us access to url module. The definition of url module is not seen to us. We just need to understand when and how to usit.  

Built-in functions have methods and classes which can be used when we require() the module.  

For example:

Here, we use the http built in module using the require(‘http’). Once we load the http module, its classes and functions like createServer can also be used.  

Node.js has a huge open source community which really boosts its ecosystem. People from around the globe contribute to the node.js community, which provides access to various modules other than the built in modules. These modules are created to solve specific problems in specific environments and then open sourced for the benefit of others. Since these modules are not part of the library, they cannot be used directly using the require unless we first install the codebase containing the module locally; once this is done, they can be integrated to our codebase. 

External modules are also known as third party modules and require package manager that maintains all the modules so that they can be accessed with ease. By default, node.js uses NPM [node package manager) package manager for JavaScript runtime environmentNPM is primarily used to install and maintain external modules in node.js application; we can install the external modules which are needed for the application using NPM. 

Built in and External modules are provided by others based on their needs. However, there might be cases where you need to build your own module for your application.  

Let’s create a module of our own named mydiff

We will put this code in a separate file called mydiff.js which provides helper function that returns difference of two numbers. This file can provide attributes to the outer world via exports, then index.js can use the exported functionality.   

Below is the content of index.js

require () will again come into play by making the attributes of local mydiff module available. Module can also allohiding to hide the functionality of the module which is not needed outside of the module. This can be done simply by not exporting the functionality via exports. In such case even though we will have mydiff.js file specified in index.js it will not be able to access the non-exported function and fail with the following error.  

This way, we can keep our codebase more organized by hiding the implementation details in a module and exposing only those parts which will be used by other parts of the codebase.  

When the modules are first loaded, they are cached. This means every call to the require () will get the same object returned for multiple calls if the call is resolved to the same file. This is an important feature as it allows us to load the transitive dependencies for returning partial objects. Module caching is done in an object in key-value pair and then we can reference the objects using the cache (require.cache). If we delete any key from this object, then we need to reload the module on next require () call. 

Caching Modules also have some caveats as the modules are cached based on their filenames. If a module is resolved to different filename based on the location of calling module it is not guaranteed that require () will always return the same object. 

Also, in case of different case-insensitive file systems, different resolved file systems points to the same file. In such a case, again, cache will treat them as separate which will result in reloading the module multiple times. For example, require (‘. /mydiff’) and require (‘. / Mydiff’) would result in two different objects. 

If a node.js module exposes an instance of some stateful object like db connection or socket etc., it is stateful module. Whereas, if a module exposes stateless entities like classes, methods etc., then it is known as stateless module. 

If an application codebase uses stateful module, we should follow the singleton pattern so that all other modules requiring stateful module access the same instance. 

Due to the concept of CommonJs system we don’t have to explicitly wrap our stateful module in Singleton patternThe first time we use the module, it will be cached for the subsequent require as while caching, node.js uses instance package address as a key. 

Stateful modules should be used with more caution than stateless modules if used in the tightly coupled architecture. 

Any component or piece of information that is needed for the working of the module is regarded as dependency, but the first thing that comes to mind while thinking about the dependencies of node.js is the content of the node_modules folder. From database connection instance to string with file path can be considered as dependency. In broader classification, dependencies are divided as ‘hardcoded dependency’ and ‘injected dependency’. 

If you hardcode the name of the dependency inside the module using a require function in the wiring pattern, it is referred to as hardcoded dependency’. If the name of dependency is instead provided as input by external entity, then it is known as dependency injection. 

Let’s see some differences between hardcoded dependency and dependency injection. 

To understand how node.js modules work, we need to know the various functionalities it offers. With this objective in mind, we first looked at the different types of node.js modules. Wthen explored built in modules, looking at different types of modules and examined what they offer and the advantages of having these modules.  

We then saw External modules and walked through how they can be included in our codebase, including how the module code could be hidden if we so wished. Finally, we saw custom modules, their benefits and how to use them effectively. We examined how modules can be cached in modules providing us with performance gains by avoiding reload several times, while also going through some caveats we should be aware of.  

We also saw how modules can be stateful and stateless and where both can fit in. Finally, we explored the module dependencies and few differences between them which helps us choose among them as per the need of the application.

Research & References of Overview of Modules in Node.js|A&C Accounting And Tax Services