NodeJS Notes - My Learnings

NodeJS Notes - My Learnings

A sneak peak inside the world of NodeJS! What is it all about and Getting started with Backend Development.

ยท

16 min read

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>
Here file_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:

  1. 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.

  2. 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 and gid is set to -1 in Windows, Because Windows does not have a concept of user IDs like Unix-based systems.
    The username of my OS is krish and the home directory is 'C:\\Users\\krish'
    The shell is set to null 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() and writeFile() methods perform Reading and Writing Operations Asynchronously.

readFileSync() and writeFileSync() 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

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 called myEvent 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 called myEvent will happen, the listener function called myFunction 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:

  1. There can be multiple on()'s for a single emit():

  1. The emit() can also contain arguments which will be passed to the listener functions:

  1. emit() function should always occur after on() 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:

  1. 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.

  2. 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:

  1. 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.

  2. 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.

  3. 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:

  1. GET: Retrieve a resource from the server
    When you enter http://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.

  2. 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.

  3. 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.

  4. 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:

  1. Step 1: Import the http module like this:

     const http = require('http');
    
  2. Step 2: Create a server using http.createServer(). Note that createServer takes in a callback function with 2 parameters - req (stands for the incoming request) and res which stands for the response to be sent by the server.

    This callback function gets executed everytime a person hits the server.

  3. 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:

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:

  1. 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.

  2. res.write() - This method is used to send the response body to the client.

  3. res.end() - This method is used to end the response process.

Check the below image ๐Ÿ‘‡

Let's break down what's happening here:

  1. Here we are responding differently to different incoming requests by using the req.url property.

  2. In every response, we are doing 3 things:

    • Setting Response Header (this contains the status code and content-type) using the res.writeHead() method

    • Setting 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.

  3. In case of resources like: /, /about and /contact the status code is set to 200 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 to 404.

  4. 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 different content-type's for different types of responses:

    • To send back JSON data as a response, we need to set the content-type to application/json

    • To send back CSS as a response, the content-type should be text/css

    • To send back JavaScript code as a response, the content-type should be text/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'})
      
  5. 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 to text/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 Logo

  • Using 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:

Twitter - Krish4856

See you next time ๐Ÿ‘‹ โค๏ธ โœจ

Did you find this article valuable?

Support Krish Jaiswal by becoming a sponsor. Any amount is appreciated!

ย