Lesson 35-Getting Started with Express Basics

Express Introduction

Express Overview

Express is a lightweight web application framework built on Node.js, widely regarded as one of the most mature, popular, and powerful frameworks in the Node.js ecosystem. It provides a robust set of features for building web and mobile applications, simplifying the handling of HTTP requests and API creation.

History and Use Cases of Express

Express was first created by TJ Holowaychuk around 2010, drawing inspiration from the Ruby on Rails framework. Since then, Express has undergone several major updates, becoming the go-to framework for web development in the Node.js community. Express is designed to be simple and flexible, avoiding rigid architectural constraints and instead providing a foundational set of tools and middleware, allowing developers to build applications tailored to their needs.

Why Choose Express as a Node.js Web Framework?

  • Flexibility: Express offers a rich set of HTTP utilities and middleware, enabling developers to create complex web applications easily. It also supports custom middleware to meet specific business logic requirements.
  • Simplicity: Express’s API is clean and intuitive, making it easy to learn and use, even for beginners.
  • Extensive Community Support: With its high popularity, Express has abundant documentation, tutorials, plugins, and community resources, making it easier to find solutions to problems.
  • Performance: Express performs exceptionally well, capable of handling large numbers of concurrent requests, making it suitable for high-performance web applications.

Installing Express and Initializing a Project

To start using Express, ensure that Node.js and npm (Node Package Manager) are installed on your computer. Follow these steps to create a new Express project:

Step 1: Create a Project Directory

Open a terminal or command-line tool and create a new directory for your project:

mkdir my-express-app
cd my-express-app

Step 2: Initialize npm

Run the following command in the project directory to initialize npm and create a package.json file:

npm init -y

This creates a package.json file with default settings, which you can edit later to add more configurations.

Step 3: Install Express

Install the Express framework using npm:

npm install express --save

The --save option adds Express to the dependencies list in package.json.

Step 4: Create the Application

Create a file named app.js in the project directory, which will serve as the main entry point for the Express application.

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

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

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

Basic Application Structure

Creating Your First Express Application

Let’s start by creating a basic Express application. Ensure Express is installed in your project, then create an app.js file as the application’s entry point.

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

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

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

This code defines a simple server that listens on port 3000 and responds with “Hello Express!” when a GET request is made to the root path /.

Setting Up Routes

In Express, routes define how the application responds to specific types of HTTP requests and URLs. In addition to basic GET requests, you can set up POST, PUT, and DELETE request types.

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

app.post('/hello', (req, res) => {
    res.send('Hello POST Request!');
});

app.put('/hello', (req, res) => {
    res.send('Hello PUT Request!');
});

app.delete('/hello', (req, res) => {
    res.send('Hello DELETE Request!');
});

Writing Middleware

Middleware is a key concept in Express, consisting of functions executed before the request reaches the route handler. Middleware can perform tasks such as executing code, sending responses, or calling the next middleware in the chain.

app.use((req, res, next) => {
    console.log('Time:', Date.now());
    next();
});

Using Middleware

Middleware can handle request headers, parse request bodies, log requests, and manage errors. For example, use the body-parser middleware to parse JSON and URL-encoded data:

const bodyParser = require('body-parser');

app.use(bodyParser.json()); // For parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // For parsing application/x-www-form-urlencoded

app.post('/data', (req, res) => {
    console.log(req.body); // Prints the JSON data sent in the request body
    res.send('Data received');
});

Responding to HTTP Requests

Express provides various methods to respond to HTTP requests, including res.send(), res.json(), res.redirect(), and res.render().

app.get('/json', (req, res) => {
    res.json({ message: 'Hello JSON Response!' });
});

app.get('/redirect', (req, res) => {
    res.redirect('https://www.example.com');
});

Practical Code Example

Below is a complete example demonstrating how to create a basic web application with different HTTP methods and middleware using Express.

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const port = 3000;

// Middleware to log requests
app.use((req, res, next) => {
    console.log(`${req.method} request received to ${req.url}`);
    next();
});

// Middleware to parse request body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// Routes
app.get('/', (req, res) => {
    res.send('Welcome to Express!');
});

app.get('/greet/:name', (req, res) => {
    const { name } = req.params;
    res.send(`Hello, ${name}!`);
});

app.post('/data', (req, res) => {
    console.log(req.body);
    res.send('Data received');
});

app.put('/update', (req, res) => {
    res.send('Resource updated');
});

app.delete('/remove', (req, res) => {
    res.send('Resource removed');
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

Template Engines

Template engines in Express are tools used to generate HTML pages by embedding dynamic data into static HTML templates. Popular template engines include EJS, Pug, and Handlebars.

EJS

EJS (Embedded JavaScript Templates) is a simple template engine that allows embedding dynamic content using JavaScript syntax.

Installing EJS

npm install ejs

Using EJS

Set EJS as the template engine in your Express application:

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

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.get('/', (req, res) => {
    res.render('index', { title: 'My EJS Page', message: 'Hello EJS!' });
});

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

Create an index.ejs file in the views directory:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title><%= title %></title>
</head>
<body>
    <h1>Welcome to <%= title %></h1>
    <p><%= message %></p>
</body>
</html>

Pug

Pug (formerly Jade) is an efficient HTML template engine that uses indentation to represent nested HTML tags.

Installing Pug

npm install pug

Using Pug

Set Pug as the template engine:

app.set('view engine', 'pug');

Create a views/index.pug file:

doctype html
html
    head
        title= title
    body
        h1 Welcome to #{title}
        p #{message}

Handlebars

Handlebars is a powerful template engine that uses double curly braces {{ }} to enclose dynamic content.

Installing Handlebars

npm install handlebars

Using Handlebars

Set Handlebars as the template engine:

app.set('view engine', 'handlebars');

Create a views/index.handlebars file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
</head>
<body>
    <h1>Welcome to {{title}}</h1>
    <p>{{message}}</p>
</body>
</html>

Rendering Views and Passing Data

In the examples above, we use the res.render() method to render views and pass data via the second parameter. For instance, in the EJS example:

res.render('index', { title: 'My EJS Page', message: 'Hello EJS!' });

Here, { title: 'My EJS Page', message: 'Hello EJS!' } is an object whose key-value pairs are passed to the EJS template for use.

Static File Serving

Configuring Static File Directories

Express uses the express.static middleware to serve static files. You need to specify one or more directories as the source for static files.

const express = require('express');
const path = require('path');
const app = express();
const port = 3000;

// Specify the public directory as the static file directory
app.use(express.static(path.join(__dirname, 'public')));

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

In this example, all files in the public directory can be accessed directly via URLs. For instance, if there is a file named style.css in the public directory, it can be accessed at http://localhost:3000/style.css.

Serving CSS, JavaScript, Images, and Other Static Resources

Static resources are typically stored in directories like public or assets. Once express.static is used to specify these directories, resources can be referenced via relative paths.

HTML Example

In your HTML files, you can reference CSS and JavaScript files like this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Web App</title>
    <!-- Reference CSS file -->
    <link rel="stylesheet" href="/css/style.css">
</head>
<body>
    <!-- Page content -->
    <script src="/js/app.js"></script>
</body>
</html>

Here, /css/style.css and /js/app.js point to files in the css and js subdirectories of the public directory.

Images and Other Resources

Images and other resources can be referenced similarly:

<img src="/images/logo.png" alt="Logo">

Here, /images/logo.png points to the logo.png file in the images subdirectory of the public directory.

Multiple Static File Directories

If your application has multiple static file directories, you can use express.static multiple times:

app.use('/static', express.static(path.join(__dirname, 'static')));
app.use('/media', express.static(path.join(__dirname, 'media')));

Requests to /static and /media paths will be served by the static and media directories, respectively.

Error Handling

Middleware for Error Handling

In Express, error-handling middleware is similar to regular middleware but has a key difference: it takes four parameters instead of three. The fourth parameter is an error object, allowing the middleware to catch and handle errors thrown during request processing.

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

// Simulate a route that may throw an error
app.get('/error', (req, res, next) => {
    throw new Error('Something went wrong');
});

// Error-handling middleware
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('Something broke!');
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

In this example, accessing the /error path throws an error, which is caught by the error-handling middleware, returning a 500 status code and an error message.

Custom 404 Error Page

A 404 error occurs when a user tries to access a non-existent page. You can customize a 404 page to provide a more user-friendly experience.

// Add 404 error handling after all routes
app.use((req, res, next) => {
    res.status(404).send('Sorry, can\'t find that!');
});

Custom 500 Error Page

A 500 error typically indicates an internal server error. You can customize a 500 page to provide more information to users when an error occurs.

// Error-handling middleware
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('Something broke!');
});

To provide more detailed error information, you can use a template engine to render a page with error details:

app.use((err, req, res, next) => {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: err
    });
});

This assumes you have set up EJS or another template engine and created an error.ejs file in the views directory to render the error page.

Share your love