Node Js Essentials Mastering Backend
Node Js Essentials Mastering Backend
Node.js has emerged as one of the most in uential and revolutionary technologies in web
popularity among developers in recent years. In this article, we will explore what Node.js is,
why it has become a preferred choice for web development, and its fascinating history.
What is Node.js?
Node.js is an open-source, cross-platform JavaScript runtime environment allowing
developers to execute JavaScript code outside a web browser. Unlike traditional JavaScript,
which runs primarily on the client side, Node.js enables the execution of JavaScript on the
server side. This means that developers can now use JavaScript to build server-side
applications, which was previously limited to other programming languages like Python or
PHP.
At the core of Node.js lies the V8 JavaScript engine developed by Google, which compiles
JavaScript code directly into machine code for e cient and lightning-fast execution. The V8
engine has played a crucial role in making Node.js a high-performance platform for building
the need for additional threads, leading to improved scalability and resource e ciency.
2. Fast and Lightweight: Node.js is renowned for its speed and lightweight nature. It
executes code swiftly by leveraging the V8 engine and o ers a non-blocking I/O model,
making it a perfect choice for real-time applications like chat applications or online
gaming.
3. Uni ed Language: With Node.js, developers can use JavaScript for both client-side
productivity. This uni ed language approach has led to the rise of full-stack JavaScript
development.
4. Massive Ecosystem (npm): Node.js boasts a vast and robust ecosystem of open-
source libraries and packages made available through the Node Package Manager
allowing developers to focus on building innovative features rather than reinventing the
wheel.
History of Node.js
The story of Node.js dates back to 2009 when Ryan Dahl, a developer, introduced this
groundbreaking technology. Dissatis ed with the limitations of traditional web servers and
seeking a more e cient approach to handling I/O operations, Dahl conceived the idea of a
asynchronous I/O with JavaScript. The prototype garnered attention within the developer
(0.1.14) in March 2010. With the introduction of npm, Node Package Manager, developers
gained access to an extensive repository of packages, signi cantly enhancing the capabilities
of Node.js.
companies like LinkedIn and Yahoo adopted Node.js for their applications, boosting their
stakeholders created the Node.js Foundation in 2015. The foundation aimed to oversee
scalable and high-performance applications. Its use cases range from building real-time chat
expanding its ecosystem, and providing valuable feedback. New features and
“Node.js goal is to provide an easy way to build scalable network programs” → Ryan Dahl,
creator of Node.js.
Understanding the Node environment is crucial to building scalable systems with it. The rst
principle to remember is that the Node.js engine chooses clarity and simplicity over
Deferred tasks are encapsulated, entering and exiting the execution context via
callbacks.
I/O operations generate event data streams that are piped through a single stack.
Concurrency is managed by the system, abstracting away thread pools and simplifying
memory management.
N/B: Managing concurrency in connection handling and application design is the key to
exploring languages, JavaScript was a good modern language without opinions on streams,
the lesystem, handling binary objects, processes, networking, and other capabilities
JavaScript was only limited to the browser. Therefore, those features were not
Here are some of the rigid principles that guided Ryan Dahl in choosing JavaScript
loop.
2. Web applications are I/o intensive, so the focus should be on making I/O fast.
Node.js is built for speed (high concurrency) and e ciency (minimal resource usage) by
reducing waste, and a waiting process is a wasteful process, especially when waiting for an
I/O operation. Therefore, JavaScript's asynchronous, event-driven design ts neatly into this
If a process's start, stop, and idle state are understood as events that can be subscribed to
and acted upon, we can begin to discuss how extremely complex systems can be
constructed within this new and, at heart, quite simple to grasp model.
What would an environment within which many clients’ jobs are cooperatively scheduled to
look like? And how is this message passing between events handled? Let’s explore two
popular options and discover the one that greatly in uences Node Architectural Design
choice.
Collaboration
Queueing
We might add a bu er (queue) between the clients and the dispatcher(Libuv) to avoid
overwhelming anyone. This is responsible for managing the prioritized queue of client tasks,
sending and receiving requests and responses from the dispatcher and worker when idle
The queue model greatly inspires the Node Architectural Design choice. However, to
implement the queueing model, the Node system is made up of three components:
V8 engine
LibUv
V8 Engine
V8 is Google’s JavaScript engine, written in C++. It compiles and executes JavaScript code
inside a VM (Virtual Machine). The Node event loop is ultimately doing the method of
LibUv
Node.js internals uses the Libuv library to enforce an asynchronous, event-
driven programming style. The core job of Libuv in Node.js is to provide an event loop and
It is a multi-platform support library focusing on Asynchronous I/O and other core utilities
indicates interest in certain events and responds to them when these events occur. Libuv
handles gathering these events from the operating system and monitoring other sources of
events. Since the event loop runs forever, users can register callbacks to be invoked when
an event occurs.
Node.js event loop is a broad topic, and I will create detailed content exploring the Event
them. When a potentially blocking task is encountered (I/O, timers, and streams), it is
handed over to the dispatcher (the libuv thread pool). Otherwise, the instruction is queued
The primary idea of Node.js is that all I/O or time-consuming operations occupy the worker's
pools which the Node service manager will hand over to the dispatcher (the Libuv thread
pool) while the remaining work (Non-I/O) tasks are sent to the single thread of V8.
The Node engine is the services manager running in nitely through the provided
instructions, prioritizing them, and returning all responses via callback to the client.
Let's see how you can create your rst Node.js application. This section will show you how to
you are a beginner, I suggest downloading Node.js from the o cial website.
[image]
O cial packages are available on the website for all major platforms (Windows, macOS, and
Linux). Download and install the appropriate package for your system.
After installing Node.js successfully, open your terminal and type the following command to
node -v
If you see Node.js with version information as shown below, then you have successfully
You can also con rm the version of NPM (Node Package Manager) that’s installed using the
command below:
npm -v
NPM is always installed with a fresh version of Node.js; you don’t need to install it separately.
editor of your choice and type the following scripts in a new index.js le.
console.log("Hello World")
Next, open your terminal to the location of your index.js le and type the following command
node index.js
If everything is successful, you should be greeted with Hello World in your terminal as the
output.
Of course, Node doesn’t end there. Next, let’s explore Node.js modules and look at some of
A module system allows us to split and include code and import code written by other
Eric Raymond proposed the Rule of Modularity: “Developers should build a program out of
simple parts connected by well-de ned interfaces, so problems are local, and parts of the
program can be replaced in future versions to support new features. This rule aims to save
One of the main problems with building scalable systems with JavaScript is the lack of
modularity or a standard interface for assembling a coherent program from many smaller
ones. For instance, a typical web application might load dependencies using a sequence of
<head>
<script src=" leA.js"></script>
<script src=" leB.js"></script>
</head>
One problem with this approach is the lack of dynamic inclusion, which requires complicated
hacks. If possible, all potential dependencies must be declared before being used. The
introduced scripts are not encapsulated, leB cannot address leA , and there are
To solve these problems, Node.js is designed around Modules System, which allows
developers to split codes into di erent les to maintain, organize and reuse code whenever
possible.
A module is nothing but a JavaScript le. Node.js has many built-in modules that are part of
the platform and come with Node.js installation, for example, HTTP, fs, path, and more.
A Node module uses two formats — CommonJS and ESM(EcmaScript). You can get a
detailed comparison of CommonJS and ESM, but a simple di erence lies with how
CommonJS uses the require method for importing modules and module.exports to export and
expose modules, while ESM uses import to import modules and export to export and expose
modules.
1. HTTP
2. Fs
3. Path
4. Process
5. URL
The http module is used to create an HTTP server in Node.js. It is one of the most popular
Node.js modules because almost every web application built with Node.js uses it.
Here’s a simple example of using http module to build a simple web server in Node.js:
In the code snippet above, I’m using the commonJS require syntax to import the http module
from Node.js.
Next, I call the createServer function from the module to create a web server. After creating
the server, it will call the callback function with the response( res ) and request( req ).
Next, I use the res property to specify what the server should return when it is called using
Lastly, I call the listen function and pass the port number I want the server to listen to. If you
node server.js
Node FS Module
The fs is the acronym for File System. It’s used to handle le systems in Node.js. This
module has many di erent methods to handle les in Node.js, using an asynchronous or
synchronous approach.
In the above code snippet, we use the readFile function from the fs module to read the
The path includes methods to deal with le paths. Node.js made working with le and
Here’s a simple code snippet for accessing a speci c le in a directory. Assuming we want to
In the code snippet above, we required both the fs and path modules since both will be
useful. Next, we use the path.join function from the path module to join the current directory
where we save this JavaScript le we are working with using the global __dirname with the
Documents folder.
Next, we use the readdir function from the fs module to read the directory content we
Lastly, we loop through all the les and log them to the console using JavaScript forEach .
The process module provides information and controls about the current Node.js process.
With the process module, you can control the current Node process.
One of the most popular uses of the process module is to return an object containing the
user environment.
process.env.NODE_ENV
process.env.API_KEY
In the script above, we use the env property of the process module to return the NODE_ENV
The url module provides utilities for URL resolution and parsing. If you need to parse your
URL, generate an acceptable URL format, or split your URL into a readable part in Node.js,
First, we require the url module and parse our URL using the parse method from the url
module. Now that the URL is parsed, we can work with di erent parts of the URL, as shown
In many ways, the success of Node.js is due to growth in the number and quality of packages
available to the developer community, distributed via the Node package management
system (NPM).
NPM is a Node package management system and online repository for publishing open-
interacting with the online repository that aids in package installation, version management,
In creating a custom package, you can make it private or public for others. We will not cover
private packages in this guide, but we will learn how to install, update, and run scripts using
NPM.
Installing packages
To install any package into your Node.js project, you need the full name of the package you
npm is the package manager and a command line utility, install is the command we want to
run, which takes in is-even as the name of the package we will pull from the online repository
Updating a package
Assuming you want to update the version of a package you installed earlier. You can use the
You can update a speci c package by specifying the version number or update all packages
Professionally, when creating a Node project, you include a package.json le to manage your
dependencies and some project metadata. You can create a blank package.json le using the
following command:
npm init -y
Specifying the -y ag means you want to accept all the defaults. Now, you can add a script
section on your package.json le to run some commands using NPM. Let’s take a look at how
{
"name": "tests",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \\"Error: no test speci ed\\" && exit 1",
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Look at the script above. The start property inside the scripts object tells NPM how to start
the Node project. Running the start command using NPM will start our Node project:
You can specify as many commands you want to run in the scripts section and run it using
Working with Node.js to create APIs is a broad topic because it covers building scalable APIs
and designing enterprise-level APIs in Node.js. We will cover API and API Design for these
However, we will learn how to build a simple web API using the Node http module and
introduce you to popular Node frameworks you can use to build scalable APIs for your
project.
In the previous lesson, we learned about the http module and how you can use it to create a
web server. Here we will build a simple API to demonstrate how to use the http module to
commands below:
mkdir node-todo-api
cd node-todo-api
Next, initialize a default package.json le to install and manage our dependencies and run
npm init -y
This command will create a new package.json le inside your root directory. Open it and
{
"name": "tests",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \\"Error: no test speci ed\\" && exit 1",
"start": "node server.js"
},
"keywords": [],
"author": "",
"license": "ISC"
}
The API will perform a basic CRUD (Create, Read, Update, and Delete) operation on an array
of todos since want to keep things very basic and not con gure any database.
The last part of the setup is using the http module from Node to create a web server for our
API. We have already done something similar above, but let’s review it again.
server.listen(3000, () => {
console.log('Server is running')
});
The code snippet above creates a simple HTTP server using the createServer method of the
http module from Node.js, and next, we listen to incoming requests on port 3000 .
operations on it. With this array, we should be able to create new todo, read todo from the
array, update the todo state, and delete the todo when done.
{
title: "Todo 2",
desc: "This is my second Todo",
completed: true,
},
{
title: "Todo 3",
desc: "This is my third Todo",
completed: true,
},
{
title: "Todo 4",
desc: "This is my fourth Todo",
completed: true,
},
{
title: "Todo 5",
desc: "This is my fth Todo",
completed: true,
},
];
To clear confusion, the nal code should look like this inside the server.js le:
});
{
title: "Todo 2",
desc: "This is my second Todo",
completed: true,
},
{
title: "Todo 3",
desc: "This is my third Todo",
completed: true,
},
{
title: "Todo 4",
desc: "This is my fourth Todo",
completed: true,
},
{
title: "Todo 5",
desc: "This is my fth Todo",
completed: true,
},
];
server.listen(3000, () => {
console.log('Server is running')
});
Creating Routes
Next, we will create routes on our server to retrieve, create, update, and delete todos from
our temporary database. Create a new routes.js le inside your root directory and add the
touch routes.js
Open the routes.js le and add the following code snippet before you move on to adding the
};
module.exports = router;
Get Routes
We will start by creating the GET routes, which we will use to retrieve all todos or a speci c
// GET: /api/todos
if (req.url === "/api/todos" && req.method === "GET") {
The code snippet above retrieves all the todos from our temporary storage using the nd()
method when the request URL equals /api/todos and the request method is GET using the
req object.
Lastly, we return the status code of 200 and the content type of application/json and the todos
Next, we will retrieve a single todo based on the URL and the ID of the URL that’s provided.
// GET: /api/todos/:id
if (req.url.match(/\\\\/api\\\\/todos\\\\/([0-9]+)/) && req.method === "GET") {
try {
// extract id from url
const id = req.url.split("/")[3];
if (todo) {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify(todo));
} else {
throw new Error("Todo does not exist");
}
} catch (error) {
res.writeHead(404, { "Content-Type": "application/json" });
res.end(JSON.stringify({ message: error }));
}
}
The code snippet above checks if the request URL matches our regex expression (that’s if it
matched /api/todos/:id , where :id equals any number) and it's a GET then we will nd the
todo using the id and return it as a response, or we return not found exception.
POST Routes
The code snippet below implements the POST request to create new todos in our
// POST: /api/todos/
if (req.url === "/api/todos" && req.method === "POST") {
try {
let body = "";
The code snippet above checks if the URL is equal to /api/todos and if the request method is
POST . Then we add the data to our temporary database without proper validation.
The request object req implements the Node.js ReadableStream interface. The stream
emits a data and end event, giving us access to the data from the request body. Next, we
listen to the data event and convert the data to a string by concatenating it to the body
variable above. In the end event, we push the body to our array after parsing using
JSON.parse function.
Lastly, we return the last added item in our array using the todos.slice method.
PUT Routes
Next, we will look at implementing the PUT request in Node.js. Take a look at this code
The code snippet above checks if the URL matches our regular expression and if it’s a PUT
request. Then we move to update the todo in our temporary database that matches the
Finally, we returned the updated data as a response. However, if any error is encountered,
DELETE Route
Lastly, we will look at implementing the DELETE request in Node.js. Take a look at this code
This code block extracts the id from the url , deletes the todo with the matching id , sends
Below is the full implementation of the server.js le. You can also visit my repository to view
});
{
title: "Todo 2",
desc: "This is my second Todo",
completed: true,
},
{
title: "Todo 3",
desc: "This is my third Todo",
completed: true,
},
{
title: "Todo 4",
desc: "This is my fourth Todo",
completed: true,
},
{
title: "Todo 5",
desc: "This is my fth Todo",
completed: true,
},
];
server.listen(3000, () => {
console.log('Server is running')
});
Lastly, we will look at how to test your Node API using Postman. You can use any HTTP client,
As demonstrated, creating scalable APIs with Node.js without any framework is possible. But
it is a di cult task to manage and requires high mastery. You will need to make sure you
cover lots of edge cases and create bug-free codes.
That is where frameworks come to the rescue. Over the years, Node.js developers have
built frameworks like ExpressJS, NestJS, and AdonisJS to make building enterprise-level and
We have already covered some of the popular Node frameworks. You can click the links
I will advise you to start with ExpressJS and then move to any other framework in the
ecosystem.