Express.js Tutorial for Beginners

Express Expert 12 min read Framework 1,280 views
Express.js Tutorial Cover Image

What is Express.js?

Express.js is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications. It's the most popular Node.js framework and makes building web applications and APIs much easier than using Node's built-in HTTP module alone.

Why Use Express.js?

Express.js simplifies web development with Node.js by providing:

  • Simplified Routing: Easy-to-use routing system for handling HTTP requests
  • Middleware Support: Modular components that can handle requests and responses
  • Template Engines: Support for dynamic HTML generation
  • Database Integration: Easy integration with various databases
  • Large Ecosystem: Extensive middleware and plugins available

Setting Up Express.js

Step 1: Create a Project Directory

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

Step 2: Initialize npm Project

npm init -y

Step 3: Install Express.js

npm install express

Step 4: Install Nodemon for Development

npm install --save-dev nodemon

Step 5: Update package.json Scripts

{
  "scripts": {
    "start": "node app.js",
    "dev": "nodemon app.js"
  }
}

Creating Your First Express App

Create a file called app.js and add the following code:

// Import Express
const express = require('express');

// Create an Express application
const app = express();
const port = 3000;

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

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

Run your application with:

npm run dev

Visit http://localhost:3000 in your browser to see your first Express app!

Understanding Routing

Routing refers to how an application's endpoints (URIs) respond to client requests. Express provides a simple and powerful routing system.

Basic Routes

// GET route for homepage
app.get('/', (req, res) => {
    res.send('Welcome to the homepage!');
});

// GET route for about page
app.get('/about', (req, res) => {
    res.send('About us page');
});

// POST route for creating data
app.post('/users', (req, res) => {
    res.send('Creating a new user');
});

// PUT route for updating data
app.put('/users/:id', (req, res) => {
    res.send(`Updating user ${req.params.id}`);
});

// DELETE route for deleting data
app.delete('/users/:id', (req, res) => {
    res.send(`Deleting user ${req.params.id}`);
});

Route Parameters

Route parameters are named URL segments used to capture values. They can be accessed using req.params:

// Route with parameter
app.get('/users/:userId', (req, res) => {
    const userId = req.params.userId;
    res.send(`User ID: ${userId}`);
});

// Multiple parameters
app.get('/users/:userId/posts/:postId', (req, res) => {
    const { userId, postId } = req.params;
    res.send(`User ${userId}, Post ${postId}`);
});

Query Parameters

Query parameters are key-value pairs in the URL after the question mark. They can be accessed using req.query:

// URL: /search?q=nodejs&sort=popular
app.get('/search', (req, res) => {
    const { q, sort } = req.query;
    res.send(`Searching for: ${q}, sorted by: ${sort}`);
});

Middleware

Middleware functions are functions that have access to the request object (req), the response object (res), and the next function in the application's request-response cycle.

Application-Level Middleware

// Custom middleware
const logger = (req, res, next) => {
    console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`);
    next();
};

// Apply middleware to all routes
app.use(logger);

// Built-in middleware
app.use(express.json()); // Parse JSON bodies
app.use(express.urlencoded({ extended: true })); // Parse URL-encoded bodies

Route-Specific Middleware

// Middleware for specific route
app.use('/admin', (req, res, next) => {
    console.log('Admin middleware');
    next();
});

app.get('/admin/dashboard', (req, res) => {
    res.send('Admin Dashboard');
});

Error Handling Middleware

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

Template Engines

Express supports various template engines for generating dynamic HTML. Let's use EJS as an example:

Install EJS

npm install ejs

Set Up View Engine

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

Create Views Directory

mkdir views

Create a Template

Create views/index.ejs:

<!DOCTYPE html>
<html>
<head>
    <title><%= title %></title>
</head>
<body>
    <h1><%= heading %></h1>
    <p><%= message %></p>
</body>
</html>

Render Template

app.get('/', (req, res) => {
    res.render('index', {
        title: 'My Express App',
        heading: 'Welcome to Express.js',
        message: 'This is a dynamic page!'
    });
});

Building a REST API

Express is excellent for building REST APIs. Let's create a simple user management API:

Mock Data

// Mock user data
let users = [
    { id: 1, name: 'John Doe', email: 'john@example.com' },
    { id: 2, name: 'Jane Smith', email: 'jane@example.com' }
];

API Routes

// GET all users
app.get('/api/users', (req, res) => {
    res.json(users);
});

// GET user by ID
app.get('/api/users/:id', (req, res) => {
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) {
        return res.status(404).json({ error: 'User not found' });
    }
    res.json(user);
});

// POST new user
app.post('/api/users', (req, res) => {
    const newUser = {
        id: users.length + 1,
        name: req.body.name,
        email: req.body.email
    };
    users.push(newUser);
    res.status(201).json(newUser);
});

// PUT update user
app.put('/api/users/:id', (req, res) => {
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) {
        return res.status(404).json({ error: 'User not found' });
    }
    
    user.name = req.body.name || user.name;
    user.email = req.body.email || user.email;
    
    res.json(user);
});

// DELETE user
app.delete('/api/users/:id', (req, res) => {
    const index = users.findIndex(u => u.id === parseInt(req.params.id));
    if (index === -1) {
        return res.status(404).json({ error: 'User not found' });
    }
    
    users.splice(index, 1);
    res.json({ message: 'User deleted successfully' });
});

Static Files

Express can serve static files like CSS, JavaScript, and images:

// Serve static files from 'public' directory
app.use(express.static('public'));

// Now you can access files like:
// http://localhost:3000/css/style.css
// http://localhost:3000/js/script.js
// http://localhost:3000/images/logo.png

Common Middleware Packages

Here are some useful Express middleware packages:

CORS

npm install cors

const cors = require('cors');
app.use(cors()); // Enable CORS for all routes

Morgan (HTTP Request Logger)

npm install morgan

const morgan = require('morgan');
app.use(morgan('combined')); // Log HTTP requests

Helmet (Security)

npm install helmet

const helmet = require('helmet');
app.use(helmet()); // Set security headers

Error Handling Best Practices

// 404 handler (must be after all other routes)
app.use((req, res, next) => {
    res.status(404).json({ error: 'Not Found' });
});

// Global error handler (must be last)
app.use((err, req, res, next) => {
    console.error(err.stack);
    
    // Don't leak error details in production
    const message = process.env.NODE_ENV === 'production' 
        ? 'Something went wrong!' 
        : err.message;
    
    res.status(err.status || 500).json({
        error: message,
        ...(process.env.NODE_ENV === 'development' && { stack: err.stack })
    });
});

Next Steps

Now that you understand Express.js basics, you can explore:

Conclusion

Express.js provides a solid foundation for building web applications and APIs with Node.js. Its minimal approach and extensive middleware ecosystem make it a popular choice among developers. Master these fundamentals and you'll be well on your way to building robust web applications.