NodeJS from scratch — Part 4
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