Modern Server-Side Development with Express.js

Overview

After we discussed about using Node.js with the http module to develop a server, we introduce another Node module, Express.js that we will use to simplify the development activities. We will follow the textbook for the lab activities. We will cover the following lessons in our textbook.

Before we start, I recommend that you read through this article from Mozilla that provides another introduction to Node and Express.

Express.js is not a web server. It is a framework that runs on top of Node’s HTTP server. Under the hood, Express still calls http.createServer()(…)

Setup Express

Express is a downloadable module that can be installed from the command line once with:

1
npm install express --save

At this point, you should familiarize yourself with the source code from the book, which is available freely at. This can be done by:

1
2
3
cd /apps
apt install -y git
git clone https://github.com/JonathanWexler/get-programming-with-nodejs.git

Node HTTP and Node Express

1
2
3
4
5
6
7
8
9
10
const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.end('Hello from Node HTTP\n');
});

server.listen(3000, () => {
  console.log('Node HTTP server listening on port 3000');
});
HTTP
  • The server is manually created (1, 3)
  • The headers are manually written (4)
  • The response is manually handled (5)
1
2
3
4
5
6
7
8
9
10
const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello from Express\n');
});

app.listen(3000, () => {
  console.log('Express server listening on port 3000');
});
Express
  • Express uses Node’s HTTP server internally
  • Headers and status codes are managed by Express.
  • Routing (GET /) is handled declaratively.
    • The response helper (res.send) handles the boilerplate

Lesson 8: Setting an app with Express.js

Expected outcome

Lesson 9: Routing in Express.js

This lesson provides a preliminary view on routing/MVC

Reading
  • Read through Lesson 9 and examine the codes in the finish folder of lesson_9 to observe how the routes are managed via Express.js
  • Run node main.js to view

Another way to approach this is to start this lesson from the end, which is the 9-3 example in GitHub.

main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
"use strict";

const port = 3000,
  express = require("express"),
  app = express(),
  homeController = require("./controllers/homeController");

app.use(
  express.urlencoded({
    extended: false
  })
);
app.use(express.json());

app.use((req, res, next) => {
  console.log(`request made to: ${req.url}`);
  next();
});

app.post("/", (req, res) => {
  console.log(req.body);
  console.log(req.query);
  res.send("POST Successful!");
});

app.get("/items/:vegetable", homeController.sendReqParam);

app.listen(port, () => {
  console.log(`Server running on port: ${port}`);
});
homeController.js
1
2
3
4
5
6
"use strict";

exports.sendReqParam = (req, res) => {
  let veg = req.params.vegetable;
  res.send(`This is the page for ${veg}`);
};

Lesson 10: EJS (Embedded JS) and Layouts

Review

First, you are to review the web page at the official website for EJS. It is strongly recommended that you pause and go through the official website to learn more about EJS.

If you are interested in learning more about EJS, here is a good tutorial entitled How To Use EJS to Template Your Node Application.

You can follow this tutorial to develop a complete front-end of a web application with EJS. But it is not required. We will move on and begin to develop our view pages following our textbook in Lesson 10.

Prior to running, need to run the following in terminal:

1
npm install express-ejs-layout
Webpage structure: layout.js

Use a layout.js to specify the structure of a web page in your project. Store the layout.js and view files in the same folder, i.e., the views folder.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Recipe App</title>
    <link rel="stylesheet" href="./css/custom.css">
    <style media="screen">
      body {
        margin: 0;
        padding: 0;
        height: 100%;
        color: black;
        text-align: center;
        font-family: 'open sans';
      }
      #nav {
        width: 100%;
        text-align: center;
        height: 60px;
        background-color: #7D498D;
      }
      #footer {
        width: 100%;
        text-align: center;
        height: 60px;
        background-color: #9C73A9;
        position: relative;
        bottom: 0;
      }
      #container {
        height: 100px;
      }
    </style>
  </head>
  <body>
    <% include partials/navigation %>
    <div id="container">
      <%- body %>
    </div>
    <div id="footer">FOOTER</div>
  </body>
</html>
Prepare view files and controllers

Third, you are to Prepare view files and controllers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// homeController.js
'use strict';
const express = require( 'express' ),
layouts = require( 'express-ejs-layouts' ),
app = express(),
homeController = require( './controllers/homeController' );
app.set( 'port', process.env.PORT || 3000 );
app.set( 'view engine', 'ejs' );
app.use( layouts );
app.use( homeController.logRequestPaths );
app.get( '/items/:vegetable', homeController.sendReqParam );
app.get( '/name/:myName', homeController.respondWithName );
app.listen( app.get( 'port' ), () => {
  console.log( `Server running on port: ${app.get('port')}` );
} );
1
2
3
4
// view file: index.js
<h1> Hello, <%= name %> </h1>
//view file in the partials folder: navigation.js
<div id="nav">TOP NAVIGATION</div>

Here the EJS tag <%= name %> replaces the name by the value of the name into the template while completing the rendering operation.

Testing
  • Test your code with the URL: http://127.0.0.1:3000/name/John
  • Test your code with the URL: http://127.0.0.1:3000/veg/banana
  • Notice that the format of the ‘include’ statement in a view file is: <% include partials/navigation %>