NodeJS from scratch — Part 4

Anuj Baranwal
6 min readJul 15, 2018

In previous parts, we discussed about —

  • basics of nodeJS
  • debugging
  • asynchronous programming
  • call stack and event loop
  • promises

Part 1 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-1-a3c1431f1e15

Part 2 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-2-3035f8f46b09

Part 3 — https://medium.com/@anujbaranwal/nodejs-from-scratch-part-3-20956ec252a3

Repo — https://github.com/anuj070894/nodejs_medium_1

In this part, we will discuss about —

  • express
  • templates
  • middlewares
  • heroku deployment

Express

It is the minimalistic nodeJS web application framework that provides a rich set of features for mobile and web applications. Very easy to create apis and performant. http://expressjs.com/

In this part, we will be building a typical web portfolio application with simple pages like Home, About, Projects, Help, etc.

To get started —

Run npm init

npm install express --save

Express will help us create a server that will us serve the pages when requests to the server is made. To do that, we need to require the express in our file. And create a new express app by instantiating it.

in express-web-app/app.js

const express = require('express');
const app = express();

Let’s create the home route for our app. To do that, we write —

app.get('/', (req, res) => {
res.send('Hello World!');
});

Instead of Hello World! , we can have <h1>Hello World!</h1> or json. We don’t have to do anything. Express helps us handle that out of the box and we don’t have to worry about. The response header content-type can be seen accordingly. text/html or application/json would have been set based on the response from the request handler.

app.get('/', (req, res) => {
res.send('Text'); // Text
// res.send('<h1>Header</h1>'); // html
/* res.send({
text: 'text'
}); */ // json data
}); // check content-type in response headers - application/json, text/html

Finally, we need to keep our server live. Therefore, it should be continuously listening on a port until it is closed explicitly.

app.listen(3000, () => {
console.log('Server running on port 3000');
});

Branch — 07_Init

Let’s add one more route /help to serve help.html when request to localhost:3000/help.html is made.

in express-web-app/public/help.html

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>Help Page</title></head><body><h1>Help Page</h1><p>Some help is needed!!!</p></body></html>

However, we have to tell express that please look for such public assets from /public directory. Whenever we need to make such configuration, we make use of something called as middlewares. Middlewares are used to provide additional functionalities by configuring express to our needs.

app.use(express.static(__dirname + '/public'); // app.use - middleware. It's telling here that the static assets will be served from /public directory relative to the appapp.get('/help', (req, res) => {res.render('help.html'); // to render html page, we use render method from res
});

However, most of the times, it won’t be that straight forward to just render the static pages. But it will be required to render the pages dynamically based on user based information (or) reusing the html templates for footer and header.

View Templating with data

To achieve this rendering of templates based on data, we use what we call as templating engine. We will be using handlebars in this part. However, there are other like jade, ejs, etc.

To install handlebars — npm install hbs --save

The default folder that express look into is views for such templates. However, we need to tell express that we will be using handlebars as our view engine.

Let’s see how we inject data into our page from response. We will be creating an About page to do that.

in express-web-app/views/about.hbs

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>{{titlePage}}</title></head><body><header><h1>{{contentHeader}}</h1></header><p>{{contentBody}}</p><footer><p>Copyright {{currentYear}}</p></footer></body></html>

in express-web-app/index.js

const hbs = require('hbs');...app.set('view engine', 'hbs'); // set express related configurations. key -> value pairs...
app.get('/about', (req, res) => {
res.render('about.hbs', {titlePage: 'About Page',contentHeader: 'About Page',contentBody: 'This is a Portfolio Website'});});...

Let’s create a Home page similar to how we created the about page

in express-web-app/views/home.hbs

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>{{titlePage}}</title></head><body><header><h1>{{contentHeader}}</h1></header><p>{{contentBody}}</p><footer><p>Copyright {{currentYear}}</p></footer></body></html>

in express-web-app/index.js

...
app.get('/', (req, res) => {
res.render('home.hbs', {titlePage: 'Home Page',contentHeader: 'Home Page',contentBody: 'Welcome to the Portfolio Website'});});...

Branch — 08_Init

Advanced View Templating with Data

As it can be seen above that home.hbs and about.hbs has footer and header components that can be made as common. To do this, we make use of something called as Partials

They are called as partials because they usually represent a partial piece of your site that common to the different web pages.

We need to register the partials with hbs in our express app.

hbs.registerPartials(__dirname + '/views/partials');

in express-web-app/views/partials/footer.hbs

<footer><p>Copyright {{currentYear}}</p></footer>

in express-web-app/views/about.hbs

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>{{titlePage}}</title></head><body>{{> header}}<p>{{contentBody}}</p>{{> footer}}</body></html>

So, using a syntax {{> header}} , we can include partials inside the page.

Registering helpers inside the partials in hbs

One very handy functionality is that we can also register helper methods with hbs that we can make use of inside the .hbs pages

hbs.registerHelper('getCurrentYear', () => {
return new Date().getFullYear();
});
inside the .hbs pages
---------------------
{{getCurrentYear}}

Instead of mundane helpers which just returns values, we can also pass parameters to the helpers.

hbs.registerHelper('screamIt', (text) => {
return text.toUpperCase();
});
inside the .hbs pages
---------------------
{{screamIt welcomeMessage}}

in express-web-app/views/home.hbs

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>{{titlePage}}</title></head><body>{{> header}}<p>{{screamIt welcomeMessage}}</p><p>{{contentBody}}</p>{{> footer}}</body></html>

Middlewares

Middlewares are to tell express that we want you to configure a bit to way how we want it to work.

Middlewares are called just before any request is actually being executed.

app.get('/', (req, res) => {res.send('Hello World');
}); // a typical request handler to the root page

If we write a middleware of the sort —

It expects a request, response and next as parameters. If we won’t call the next inside the middleware, it won’t execute the request handler, e.g., res.send(‘Hello World’);

This is sometimes useful when site is under maintenance.

app.use((req, res, next) => {res.render('maintenance.hbs'); // we didn't call next
});

However, the main purpose of such a middleware is to log the request details. We will be doing that task in this part.

app.use((req, res, next) => {const currentTime = new Date().toString();const log = `${currentTime}: ${req.method} - ${req.originalUrl}`;fs.appendFile('server.log', log + "\n", (error) => {if (error) {console.log('Some error has happened while opening the file!!!');}});next(); // we need to call next from the middleware to complete the request from happening});

The order in which middlewares are written is very important. They get executed in the same order in which they are written.

Branch — 09_Init

Deploying your apps

We will be deploying our app to heroku. Heroku lets us deploy, run and manage applications written in nodeJS and lot other programming languages. Deployment can never get any simpler than with heroku.

Make sure to commit all your changes in your repo.

https://devcenter.heroku.com/articles/heroku-cli#download-and-install — Toolbelt for heroku can be downloaded from here. It’s just clicks and install

Once done, we need to modify our package.json to tell heroku how to pick the starting point for our app

in express-web-app/package.json

{"name": "express-web-app","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1","start": "node index.js"},"author": "","license": "ISC","dependencies": {"express": "^4.16.3","hbs": "^4.0.1"}}

in express-web-app/index.js

We also need to configure the port details dynamically.

const port = process.env.PORT || 3000;
...
app.listen(port, ...)

Run heroku login to login to your heroku platform.

heroku create to add the heroku remote repository locally

git push heroku to push the code to heroku servers

heroku open to open the link in the browser

And that’s it. Your app is LIVE!!!

Branch — 10_Init

Every time, you add a new feature, all you have to do is —

git push heroku

And that’s it for this part.

In this part, we discussed about —

  • express
  • web application
  • templates
  • middlewares
  • heroku

See you in next part :)

Part 5 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-5-3d3e3a84b64

Part 6.1 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-6-1-api-development-5dee11785d62

Part 6.2 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-6-2-api-development-f92f76eb3521

Part 6.3 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-6-3-api-development-9b046fed7364

Part 6.4 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-6-4-api-development-38d600a35ad9

--

--

Anuj Baranwal

Full Stack Web Developer @AdobeSystems Bangalore. Sometimes I code, I draw, I play, I edit and write