Section 1

Learning Objectives

  • Students Will Be Able To:

    • List the Fundamental Capabilities of Web Frameworks
    • Create a Basic Express Web App
    • Define Basic Routes
    • Respond to HTTP Requests
    • Render Dynamic Views


Roadmap

  • Setup
  • The Three Fundamental Capabilities of Web Frameworks
  • Intro to Express
  • Express "Hello World"
  • Basic Structure of an Express App
  • Our First Route
  • The Route's Callback Function
  • Practice - Define Another Route
  • Ways to Respond to a Request
  • Rendering Views
  • Redirecting

arthur_node_jsx_diagram_photoshopped

Setup

  • Create a folder called express-practice and then change into it
$ mkdir express-practice
$ cd express-practice
  • Create a file inside this folder called server.js
$ touch server.js
  • Then create a package.json and accept the defaults using this command:
$ npm init -y
  • Open the project's folder in VS Code.


The Three Fundamental Capabilities of Web Application Frameworks

  • Web Application Frameworks have three capabilities fundamental to writing a back-end web application:

    1. The ability to define routes
    2. The ability to process HTTP requests using middleware
    3. The ability to use a view engine to render dynamic templates
  • Over the next few lessons, you will learn about how the Express framework implements these three fundamental capabilities.



Express Framework - Intro

  • Express is the most popular web framework for Node.js.
  • It is minimalistic and lightweight, especially when compared to massive frameworks like Django and Rails.
  • Express uses Node's built-in HTTP module to listen for, and respond to, HTTP requests - Express simply adds those three web application capabilities on top of Node


Install the Express Module

  • Let's use npm to install the Express module in this project:

    $ npm i express

    Note that i is a shortcut for install



Express - Hello World!

  • Let's write the obligatory "Hello World!" application:

    // Load express
    const express = require('express');
    
    // Create our express app
    const app = express();
    
    // Define a "root" route directly on app
    // Tomorrow, we'll use best practice routing
    app.get('/', function (req, res) {
      res.send('<h1>Hello World!</h1>');
    });
    
    // Tell the app to listen on port 3000
    // for HTTP requests from clients
    app.listen(3000, function () {
      console.log('Listening on port 3000');
    });


  • Run the app:

    $ node server
  • Browsing to localhost:3000 will hit our app's root route that we defined and return "Hello World!".
  • Using DevTools, we will find that despite just sending back the text of <h1>Hello World!</h1>, the browser "built" a minimal HTML document to display it in.
  • The send method is a general purpose way to respond to the request, however, soon we'll be using more specific methods.


Basic Structure of Express App

  • Here is a helpful outline of what a typical Express app does - let's put this guide right in our server.js:
// Require modules
const express = require('express');

// Create the Express app
const app = express();

// Configure the app (app.set)


// Mount middleware (app.use)


// Mount routes
app.get('/', function(req, res) {
  	res.send('<h1>Hello World!</h1>');
});

// Tell the app to listen on port 3000
app.listen(3000, function() {
 console.log('Listening on port 3000');
});


Our First Route

  • Let's replace the content we just sent from our route with something else.

    // Mount routes
    app.get('/', function(req, res) {
      res.send('<h1>Hello Express</h1>');
    });
  • Refreshing the page will reveal that it didn't work! This is because we have to restart the server, or...


Nodemon

  • nodemon is a popular development tool used for automatically restarting our Express app when we save changes.
  • If you are unsure if you've already installed it, you can make sure you have it or at least ensure you have the latest version by running:

    $ sudo npm i -g nodemon

    Command line tools are installed using the -g (global) option

  • Now, thanks to the main key in package.json, we can start the server by simply typing nodemon.
  • Let's move on to routing...


Our First Route (Cont)

  • Like most web frameworks, Express uses the HTTP Method and the Path of the HTTP request to match a route defined in the application.
  • In our first route, we defined a route using the get method on the Express app object.
  • The get method defines a route that listens for a GET request. There are other methods such as post, put and delete, that map to the other HTTP verbs.
  • The first argument provided to app.get, /, defines the path for the route. In this case the root of the application, i.e., just the host name like localhost:3000.
  • In Express, all strings used to define a path should start with a forward-slash character (/).
  • In tomorrow's Express lesson, we'll learn a preferred way of defining routes using the Express Router object, but you need to be aware of defining routes this way as well.


The Route's Callback

  • The second argument provided to app.get() is a callback function:

    app.get('/', function(req, res) {
      res.send('<h1>Hello Express</h1>');
    });
  • Express will execute route's callback function only when a matching HTTP request (HTTP Method + Path) is received.
  • The route's callback function:

    app.get('/', function(req, res) {
      res.send('<h1>Hello Express</h1>');
    });

    defines two parameters: req & res

  • req: Represents Express's request object, and
  • res: Represents Express's response object
  • Express provides those two objects as arguments when it invokes the callback.
  • The request object has properties and methods used to access information regarding the current HTTP request, including any data being sent from the browser.
  • The response object contains properties and methods used to end the request/response cycle - like we've done so far using the res.send method.


Practice - Define Another Route (3 mins)

  • Define another route that matches a get request to a path of /home that sends a text response of <h1>Home Page</h1>.
  • Test it by browsing to localhost:3000/home.


Review Question - Routing

  • Is it okay to define more than one route on the same path?
    For example:
app.get('/cars', function(req, res) {
  res.send("Here's a list of my cars...");
});

app.post('/cars', function(req, res) {
  res.send('Thanks for the new car!');
});


Ways to Respond to a Request

  • So far we have responded in our route handler (callback) code by using the res.send method.
  • The Express docs for the Response object explains the other ways to respond to the HTTP request.
  • Here are the methods we'll use the most:

    • res.render() - Render a view template and send the resulting HTML to the browser.
    • res.redirect() - Tell the browser to issue another GET request.
    • res.json() - Send a JSON response (used when we build an API).


Rendering A View

const fs = require('fs') // this engine requires the fs module like we did Saturday
app.engine('madeline', (filePath, options, callback) => { // define the view engine called hypatia
  fs.readFile(filePath, (err, content) => {
    if (err) return callback(err)
    // this is an extremely simple view engine we'll be more complex later
    const rendered = content.toString()
      .replace('#title#', '<title>' + options.title + '</title>')
      .replace('#message#', '<h1>' + options.message + '</h1>').replace('#content#','<div>'+ options.content + '</div>' )
    return callback(null, rendered)
  })
})
app.set('views', './views') // specify the views directory
app.set('view engine', 'madeline') // register the hypatia view engine

After the code above

  • Make a file called template.madeline in the views folder

    <head>
    #title#
    </head>
    <body>
    <header>#message#</header>
    #content#
    </body>

Then in the server.js

app.get('/', (req, res) => {
  res.render('template', { title: 'Hey', message: 'Hello there!', content: 'I am the Boss Ricky Ross' })
})

app.get('/about-me', (req, res) => {
  res.render('template', { title: 'Hey', message: 'Rick Ross!', content: 'The most underated Rapper in the game' })
})

app.get('/another-one', (req, res) => {
  res.render('template', { title: 'We The Best', message: 'Who!', content: 'We Taking Over, Major Key Alert, Yall know who it is, All I do is win' })
})
  1. http://localhost:3000/
  2. http://localhost:3000/about-me
  3. http://localhost:3000/another-one

Essential Questions Back to The Professionalism

❓ When we define routes in a web app, we are mapping HTTP requests to ____.

❓ What method do we call to render a view and on what object does that method exist?

Copyright © Per Scholas 2023