NodeJS Notes - My Learnings
A sneak peak inside the world of NodeJS! What is it all about and Getting started with Backend Development.
Hello folks ๐
From the past one week, I have been learning about NodeJS and so I thought - "How about sharing my learnings with folks here?"๐จโ๐ป And Here I am....
In this blog, Let's take a brief look at @nodejs, What it is and what can you do with it.๐คฉโจ
๐จ A Word Of Caution ๐จ
This blog post was originally written to come out as a Twitter thread, But due to some suspicious problems regarding the media, it failed! So I decided to write a blog on it!This blog contains lots of images (~around 25 images), Most of them being code snippets where the comments in the code are self explanatory as to what is happening (Hence I won't be providing much explanation about it).
So Be Prepared for a lot of images coming your way! ๐ฅท
What is Node?
Node is an environment in which you can run JavaScript code "Outside the web Browser". Node be like - "Hey bro, you give your JS code to me and I'll run it ๐".
It uses Google's V8 Engine to convert JS code to Machine code.โจ
Since Node runs JS code outside the web browser, this means that it doesn't have access to Browser API's like: DOM (Document Object Model) or the 'window' object or event the localStorage.
This means at any point in your code, you can't type in document.querySelector()
or alert()
as these will produce errors. Remember: Node is a "Server Side Technology" and the Browser API's are "Client Side Stuff".
The Frontend peeps don't become sad as there is more to it! You may ask what does Node have to offer, so here is the answer: Node provides you with lots of API's and Modules with which you can perform a variety of operations like File Handling, Creating Servers and much more!
Global Variables
Starting with it, Node provides global variables which store important information ๐
Modules in NodeJS
Modules are essentially reusable pieces of code that can be imported and used in other files or projects.
Let's say you have defined a lot of functions in your code which works with lot's of JSON data. Losing your sleep and increased anxiety levels are common side effects of keeping all this stuff (functions + data + some other logic) in one single file.
So you, Being a clever programmer, thought of making a separate file for the JSON data and another separate file for keeping the functions. Now you can simply import the data and the functions whenever you want. This method increases efficiency as your file size reduces drastically and This is the concept of modules!
Actually, We can make our own modules! So the idea is -
We can define a function that will simply console.log()
a greeting message and we can keep it in File 1.... And then we can import it in File2 and use it there.
How Interesting? ๐
We can do it like this:
Note that to run your JS code using NodeJS, Follow these steps:
Open VSCode Integrated Terminal > Run:node <file_path>
Herefile_path
is the path of the JS file you want to execute.In the above image, I executed the
app.js
file by running:node app.js
Types Of Modules
There are 2 types of modules in NodeJS:
Built In Modules - These are modules included in Node by default. Hence they can be used without installation. You just need to import them and get started.
External Modules - These are modules created by other developers which are not included by default. Hence you need to install them first before using them.
Here is an image of popular built-in modules in NodeJS and what can you do using them:
OS Module
The OS Module (as its name implies) provides you methods/functions with which you can access information about your Operating System.
To use this module, the first step is to import it like this:
const os = require('os');
This is how I used the OS Module to get information about my Windows Operating System:๐
As you can see in the last image (above โ๏ธ):
521105
is the number of seconds my system has been running since it was last rebooted{ uid: -1, gid: -1, username: 'krish', homedir: 'C:\\Users\\krish', shell: null }
The
uid
andgid
is set to-1
in Windows, Because Windows does not have a concept of user IDs like Unix-based systems.
Theusername
of my OS iskrish
and the home directory is'C:\\Users\\krish'
Theshell
is set tonull
because the concept of a default shell does not exist on Windows. Windows has a default command interpreter program called Command Prompt (cmd.exe), which runs commands and manages the system.{ name: 'WindowsNT', // Name of my OS release: '10.0.22621', // Release Version of my OS totalMem: 8215212032, // Total Memory Available in bytes (~ 8 GB) freeMem: 1082208256 // Free Memory Available in bytes (~ 1 GB) }
PATH Module
The PATH module comes in handy while working with file and directory paths. It provides you with various methods with which you can:
Join path segments together
Tell if a path is absolute or not
Get the last portion/segment of a path
Get the file extension from a path
and much more!
View the PATH Module in action in the below code images ๐
Note: The path separator is different for different systems!
- In case of Unix Based OS, The path separator is/
(forward slash)
- In case of Windows, The path separator is\
(backward slash)Remember,
\
(backward slash) is treated as an escape character.
Hence to use\
as a literal, we need to escape it using another\
In simple terms:\\
(double back-slash) represents\
(single back-slash)Hence the absolute path of the
app.js
file would be:
In Unix Based OS (Linux/MacOS):
C:/Desktop/NodeJSTut/myFolder/app.js
In Windows:
C:\\Desktop\\NodeJSTut\\myFolder\\app.js
FS Module
This module helps in File Handling Operations such as:
Reading a file (Sync or Async Way)
Writing to a file (Sync or Async Way)
Deleting a file
Reading the contents of a directory
Renaming a file
Watching for changes in a file
and much more ๐๐ธ
(โ ๏ธ Lot of code images coming your way โ ๏ธ)
Let's See The FS Module In Action:
Creating a directory - mkdir
Creating & Writing to a File (Async) - writeFile
newfile.txt
was created and the data was written to it:
Reading File (Async) - readFile
Note that
readFile()
andwriteFile()
methods perform Reading and Writing Operations Asynchronously.
readFileSync()
andwriteFileSync()
are 2 alternatives to perform the same operations Synchronously! CODE:
// Write to file synchronously fs.writeFileSync('./fsFolder/newFile.txt', 'Hi There') // Read file synchronously const fileData = fs.readFileSync('./fsFolder/newFile.txt', 'utf-8') console.log(fileData); // Hi There
Reading Contents of a Directory - readdir
Renaming a file - rename
Here the file name was successfully renamed from newFile.txt
-> renamed.txt
Deleting a File - unlink
Event Driven Programming
Event-driven programming is a programming paradigm where program flow is largely determined by events or user actions, rather than by the program's logic. In event-driven programming, the program listens for events, and when they occur, executes the code that should run in response to that event.
An event could be anything from a mouse click, a button press to the arrival of new data in the system.
In this section of the blog we will be learning about Events In NodeJS. Although we may not be using Events regularly for our day-to-day coding tasks directly, But a lot of NodeJS Modules uses Events under the hood, Hence it becomes important to know what is Events and how do they work in NodeJS.
Below is the implementation of Events in NodeJS:
Remember 2 things:
The
emit()
method causes an event to happen / It makes an event occur.
For example,emit('myEvent')
- This causes an event calledmyEvent
to occur.The
on()
method is used to listen for an event and when the event occurs, it runs a listener function which is usually some JS code to run in response to the event.
For example,on('myEvent', myFunction)
- This statement simply means that "Whenever an event calledmyEvent
will happen, the listener function calledmyFunction
will be executed in response to it."
Points To Be Noted My Lord...
There are 3 points to be noted while working around with Events in Node.
Each point in shown in action in the below images:
- There can be multiple
on()
's for a singleemit()
:
- The
emit()
can also contain arguments which will be passed to the listener functions:
emit()
function should always occur afteron()
function:
HTTP Module
The HTTP Module helps you create Web Servers!
HTTP stands for Hypertext Transfer Protocol, it is a protocol that transfers data over the internet and allows communication between clients and servers. Here's how the communication happens between Client's and Server's:
The client sends a request to the server in the form of a URL. The request can also contain additional information, such as headers and query parameters.
The server processes the request, performs necessary operations, and sends a response back to the client. The response contains a status code, headers, and the response body with the requested data.
Components Of Request - Response
Both the Request (Sent by Client to Server) and the Response (Sent by Server to Client) comprises of 3 parts:
The Status Line: This is the first line of the request or response. It contains information about the message, such as the method used, URL, protocol version, etc.
The Header: This is a collection of key-value pairs, separated by colon.
The headers include additional information about the message such as the content type, content length, caching information, etc.The Body: The Body contains the actual data being sent or received. In the case of requests, it might contain form data or query parameters. In the case of responses, it could be HTML, JSON, XML, or any other data format.
The 3 components of a Request and Response is demonstrated in much detail in the below image:
What are HTTP Methods?
HTTP methods, also known as HTTP verbs, are actions that a Client can perform on a Server. The 4 HTTP Methods are:
GET: Retrieve a resource from the server
POST: Insert a resource in the server
PUT: Update an existing resource in the server
DELETE: Delete a resource from the server
This might sound complicated, But Let's try to understand these methods with the help of an example:
GET: Retrieve a resource from the server
When you enterhttp://www.google.com
in your web browser's address bar and press enter, your browser sends a HTTP GET request to the Google server asking for the HTML content of the Google homepage, which is then rendered and displayed by your browser.POST: Insert a resource in the server
Imagine you're filling out a registration form to create an account on Google. When you submit the form, your browser sends a POST request to Google's server with the data you typed in the form fields like:
- Username
- Age
- Birthdate
- Address
- Phone Number and Email
- Gender and so on
The server will then creates a new user account in its database storing all the information sent to it using the POST Request.
Hence, a POST Request is used to add/insert a resource in the server.PUT: Update an existing resource in the server
Now imagine you want to update your Google account's password. You would send a PUT request to the server with the new password. The server would then update your user account in its database with the new password.DELETE: Delete a resource from the server
Finally, imagine you want to delete your Google user account. You would send a DELETE request to the server indicating that you want your account to be deleted. The server would then delete your user account from its database.
Note that these are just examples; The actual requests and their purposes may vary.
To see more examples of HTTP Methods, You can refer this image:
What is Status Code?
HTTP status codes are three-digit numbers that indicate the status of a HTTP request made to a server. They are server responses that provide information about the request's outcome. Here are some of the most common HTTP status codes and what they represent:
Let's Create A Server
Let's Finallllyyy Skip To The Good Part ๐ฅณ๐ฅ
Let's learn how to create a web server ourselves:
Step 1: Import the
http
module like this:const http = require('http');
Step 2: Create a server using
http.createServer()
. Note thatcreateServer
takes in a callback function with 2 parameters -req
(stands for the incoming request) andres
which stands for the response to be sent by the server.This callback function gets executed everytime a person hits the server.
Step 3: Listening the server at some port using the
listen()
method.
Read through the comments in the below code image for more details:
Note to send back the response, we are currently using a method called:
res.end()
So, We made a server that renders a simple Hello World
message every time someone tries to access it. This is good enough for now but there is a problem....
The problem is that for every route, the server sends the same message. For example, If I try to access the about page or the contact page, Still the server shows the same message
/
-> Hello World/about
-> Hello World/contact
-> Hello World
There is a simple way to fix this: There is a url
property in the req
object which gives the URL / resource the client is trying to access.
Suppose if I type in: localhost:5000/about in my web browser's search bar, This means I am performing a GET Request on the server and I am trying to access the /about
page. So In this case the req.url
stores /about
.
Similarly for the below requests, the value of req.url
will be:
URL | req.url |
localhost:5000 | / |
localhost:5000/about | /about |
localhost:5000/contact | /contact |
localhost:5000/error | /error |
Thus we can use the req.url
property to listen to requests and respond to them differently. This is shown in action in the below image.
Now we have a perfect server that responds to different requests differently. We are sending back responses using a method called res.end()
. However, there is an even better way of sending back a response by using 3 methods:
res.writeHead()
- This method is used to send the response headers to the client. The status code and headers can be set using this method.res.write()
- This method is used to send the response body to the client.res.end()
- This method is used to end the response process.
Check the below image ๐
Let's break down what's happening here:
Here we are responding differently to different incoming requests by using the
req.url
property.In every response, we are doing 3 things:
Setting Response Header (this contains the status code and
content-type
) using theres.writeHead()
methodSetting Response Body using the
res.write()
method. Note that instead of sending simple messages, we are actually sending some HTML code in this case.Closing the response process using the
res.end()
method.
In case of resources like:
/
,/about
and/contact
the status code is set to200
which means that the request to access a resource was successful. But if the client tries to access some other resource, he simply gets back an error message and the status code is set to404
.Here the
'content-type': 'text/html'
is a way of telling the browser, How it should interpret and display the response. In this case, we are telling the browser to interpret the response as some HTML code.
There are differentcontent-type
's for different types of responses:To send back JSON data as a response, we need to set the
content-type
toapplication/json
To send back CSS as a response, the
content-type
should betext/css
To send back JavaScript code as a response, the
content-type
should betext/javascript
, and so on...// writeHead() takes in 2 parameters: // 1st param: Status Code // 2nd param: This is the additional headers which // should be in the form of a JS Object with key: // value pairs res.writeHead(200, {'content-type': 'text/html'})
Setting the content type is very important as it determines how the web browser interprets the response. For example: If we just change the content-type from
text/html
totext/plain
, this is how the response will be displayed in the web browser:
Let's Serve Something Interesting
Till now we have an idea of how to set up web servers but we haven't built anything interesting. So Let's add some fun to our lives.
In the last section of this blog, we will be serving this navbar:
Since this is not a Frontend related blog, we will not be building this navbar from scratch. Instead, you can head over to this GitHub repo and copy the contents of the navbar-app
directory and set it up locally: John Smilga's GitHub repo
So the idea is to:
Set up this folder locally
Using the
fs
module to read the contents of the HTML, CSS, JS file and the LogoUsing the HTTP Module to render the files when someone tries to access the
/
route or the home page.
So Let's Get Started:
In the below image, we are using the fs
module's readFileSync()
method to read the contents of the HTML, CSS, JS and logo. Note that we are going to serve the contents of the file and not the file itself. Hence readFileSync()
comes into picture.
Then, we serve the contents of the HTML file (stored in homePage
variable) using the res.write()
method. Remember to set the content-type
as text/html
as we are serving HTML content. We have also set up responses for /about
route and also a 404 page.
We see that the other routes work fine, but the home page doesn't look good. The problem is that we only see the HTML being displayed and not the other stuff like CSS, Logo, etc.
If we try to check what are the request's being made by the web browser to the server by adding this in Line No: 16
console.log(url)
Once we refresh the page, we see that initially the browser asks for the home page and makes a GET request with the /
URL and afterward makes 3 more requests -
/style.css
- asking for the CSS file/browser-app.js
- asking for the JS file/logo.svg
- asking for the logo
From this, we can infer how browsers work!
Note that we are only providing the index.html
page as the response. Once the browser receives the HTML content, it interprets it and starts displaying the elements. While parsing HTML, if the browser encounters any additional resource like CSS Page or JS page, It will make a request to the server for the same.
Since we are not sending the CSS, JS and Logo in the response, we do not see them on the screen. This can be fixed by adding some more if()
's in the code and sending those resources which the browser asks for and BOOM This bug is fixed!
Conclusion
With this we come to the end of this blog, I hope you liked it! Do share your opinions about this blog in the comments below.
View my profile on Hashnode to read more such blogs. Connect with me on Twitter:
See you next time ๐ โค๏ธ โจ