In this article, we are going to learn how Nodejs works by creating a simple web app. The idea of web app is whenever a user requests for our site he/she will be presented with a text field where he/she can write a message. After entering the message, the message is sent to the host server where it is stored in JSON format. Then we will create another page display
where users can see all the messages which are entered. To make our web page dynamic we will also be using ajax call which will make a call to the server for JSON data every 1 second.
What is Nodejs
Nodejs is an asynchronous, event-driven javascript framework built on top of Google Chrome’s JavaScript V8 Engine. It is a cross-platform library for running JavaScript application which is used to created networking and server-side applications.
Nodejs is basically javascript plus a bunch of C/C++ under the hood for things like filesystem, creating Http or TCP servers.
The advantages of node is it is a single-threaded model. This simply means it does not make the program wait, but instead, it registers a callback and let’s program continue. Because of this feature, it can handle concurrent operations without multiple threads of execution.
Installing Nodejs and necessary packages
You can download Nodejs binaries from here. Now let’s install packages which we will be needing for app. But first, let’s create a directory called NodeWebApp
.
mkdir NodeWebApp && cd NodeWebApp
Then we will initialize our Nodejs project with default setting by executing the following command:
npm init -y
Now create index.js
file in that directory which will be the entry point of our web app.
Let’s now install the necessary packages:
npm i -D express nodemon pug browser-sync body-parser
Package Description:
- express: It is a Nodejs framework used to build web applications. It is a minimal and flexible framework which is specifically designed for building single-page,multi-page, and hybrid web application.
- pug: Pug is the middleman. It is a template engine for Nodejs. A template engine allows us to put data given by the server and produced the required HTML, which is then rendered by the browser.
- browser-sync: browser-sync automatically reloads our web page whenever there is change is HTML or CSS. You will need the following line added into your `
package.json
file:
....
"scripts": {
"dev": "nodemon ./index.js",
"ui": "browser-sync start --proxy=localhost:8000 --files='**/*.css, **/*.pug, **/*.js' --ignore=node_modules --reload-delay 10 --no-ui --no-notify"
},
....
- body-parser: Used to parse incoming requests.
- nodemon: It is used to monitor our project source code and automatically restarts whenever some changes are made in the project. To run these packages you have to open your
package.json
file. In the script part add the following line:
....
"scripts": {
"dev": "nodemon ./index.js"
},
....
Now, all that all things are set up let’s write our web app. But before that create two new folders named public
and views
. The public
folder will contain all our static files while views
will contain our pug templates. Also, you will need to edit yourindex.js
file as follows:
const express = require("express");
const path = require("path");
const app = express()
const port = process.env.PORT || "3000"
app.set("views",path.join(__dirname,"views"));
app.set("view engine","pug");
app.listen(port, 'localhost',() => {
console.log(`LISTENING AT http://localhost${port}`);
app.use(express.static(path.join(__dirname, "public")));
});
The first two lines are just importing our express
and path
module. The next line creates an instance of express()
. The port
variable is where our server would be listening.
The app.set
method is used to tell Nodejs that we are going to use Pug as our view template engine.
app.listen
method is used to start server which takes port
and IP address.
Creating WebApp
index File
First, let’s write our index page. Go to your views directory and create two files indexlayout.pug
and index.pug
. In the indexlayout.pug
write following line:
block variables
doctype html
html
head
link(rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous")
link(rel="stylesheet" href="/style.css")
#{title}
body
div#root
block layout-content
Note: For CSS I have use bootstrap
Notice that this template uses the title variable to render the document title of a page. This variable value will be passed from the server.
Next, let’s write our index.pug
file:
extends layout
block layout-content
div.container
form(action="goodbye",method = 'post')
div(style = "width: 30rem").card
div.card-body
h1.display-4 Write Something..
textarea(name="message",rows="4",cols="40")
br
button(type = "submit").btn.btn-primary Send
Note: The extends and block are used to join these two templates. This is also known as template inheritance
In this template, we have given an input filed where the user will type the message and a button to submit it. To submit the user response I have used “form” which uses post
method and redirect user “goodbye” page.
Now open up your index.js
file and write the following:
app.listen(port, 'localhost',() => {
console.log(`LISTENING AT http://localhost${port}`);
});
app.get("/",(req,res) => {
res.render("index",{title:"BloggerDrive"});
});
In the above code, we have created simple route handler for the HTTP GET/request that replies with our index.pug
template.
Note: This pug template is converted into HTML and then rendered by the browser
The app.get
method takes the first argument as path from which the request is invoked, and the second argument is call back function.
Under the call back function, we use res.render
method to render our HTML string. Which takes the first argument as the file path of the “view” file(pug file) to render. Its second argument is optional and represents an object that is passed from the controller to the template. The properties of this object become local variables in the template.Therefore, { title: “BloggerDrive” } defines a local title variable in index.pug. However, index.pug doesn’t use title locally; this value is used by the template it extends: displaylayout.pug.
Now let’s start our server. write the following two commands:
npm run dev
npm run ui
First command will start the server and second command will open up the browser.
OUTPUT:

goodbye layout
Now let’s write our goodbye layout which will invoke whenever users submit the message or whenever users click on the button.
extends layout
block layout-content
div.container
div(style = "width: 30rem").card
div.card-body
h1.display-3 Thanks !!
a(href="/")
button.btn.btn-primary Back
Now open the index.js
file and write the following code:
const path = require("path");
const bodyParser = require('body-parser');
var fs = require('fs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post("/goodbye",(req,res) => {
var data_json = {
messages:[]
}
res.render("goodbye");
fs.readFile('data.json',(err,content) => {
if (err)
{
if (err.code == 'ENOENT') {
data_json.messages.push(req.body);
fs.writeFile("data.json",JSON.stringify(data_json),'utf-8',(err) => {
if(err) throw err;
else
console.log("COMPLETED")
});
}
else throw(err);
}
else {
data_json = JSON.parse(content);
data_json.messages.push(req.body);
fs.writeFile("data.json",JSON.stringify(data_json),'utf-8',(err) => {
if(err) throw err;
else
console.log("COMPLETED")}
);
}
});
});
We have used here app.post
method to route our HTTP post request. Invoked by our form which we have created in index.pug
file. The arguments are similar to app.get
request.
Under callback function is where we write our data to JSON format and save it to the disk. For accessing our disk we use fs
module.
What we do here is first we read the “data.json” file and if the file is not created we create the new file and write the data which in our case are the messages in JSON format to the “data.json” file and save it. If the “data.json” file exists we read the entire file put it into the “data_json” object then push the new message to this object and then write back the whole JSON object to the “data.json” file.
OUTPUT:

display layout
This layout will render all the messages which are sent by the user. To make this dynamic we will use ajax call which will call for data from the server at ever 1 second and any new messages will be rendered automatically without reloading the server.
Let’s write our displaylayout.pug
file:
block variables
doctype html
html
head
link(rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous")
script(src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js")
link(rel="stylesheet" href="/style.css")
#{title}
body
div#root
block layout-content
Next, we write our display.pug
file:
extends displaylayout
block layout-content
script(src="display.js")
div(id = 'my-content')
Now under your public folder create a new file display.js
and write the following line of code:
$(document).ready( () => {
setInterval( () => {
$.ajax({
url: 'dataAPI/',
type: 'GET',
dataType: 'json',
success: (data) => {
data = JSON.parse(JSON.stringify(data))
if(data.messages.length === 0)
{
$('#my-content').html("<p class = 'lead'> Waiting for messages .... </p>");
}
else {
var result = $("<div/>");
data.messages.forEach( (item,index) => {
result.append(
" <div class = 'card' style = 'width: 30rem'>" +
" <div class = 'card-body'> " +
" <p class = 'lead'>" + item.message + "</p>" +
"</div>" +
"</div>" +
"</br>"
);
});
$('#my-content').html(result);
}
}
});
},1000);
});
The ajax function here does a GET request to /dataAPI
. The server responds this by giving a JSON response which will contain all the messages. Then we simply iterate to all the messages and prints it in a card layout. The setInterval
method is used to get API requests every second.
Now we have to pass contain of data.json
file to the client whenever we get the GET request for /dataAPI. Open up your index.js
file and write the following:
app.get("/dataAPI",(req,res) => {
var data_json = {
messages:[]
}
fs.readFile('data.json',(err,content) => {
if (err) {
console.log(err);
}
else {
data_json = JSON.parse(content);
}
res.send(data_json);
})
});
app.get("/display", (req,res) => { res.render('display',{title:"Bloggerdrive"}) } );
Whenever server gets the GET request for “/dataAPI”. It reads the data.json
file convert it into JSON format and sends it using res.send
method.
Any GET request to the “/display” will render our display.pug
template.
OUTPUT:
Saved as a favorite!, I really like it!
Thanks!!
tҺe website іѕ really good, I like it!
Thank You 🙂
I just turned 70 this year and I really like your writing!