Lesson 5 of 6
5 min read
Node.js

Express.js Basics

Get started with Express.js, the most popular Node.js web framework

What is Express.js?

Express.js is a minimal and flexible Node.js web application framework that provides a robust set of features for building web and mobile applications. It's the de facto standard for Node.js web development.

Getting Started

# Create a new project
mkdir my-express-app
cd my-express-app
npm init -y

# Install Express
npm install express

Your First Express Server

// server.js
const express = require('express');
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 on http://localhost:${PORT}`);
});

Routing in Express

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

// GET request
app.get('/users', (req, res) => {
  res.json({ users: ['Alice', 'Bob', 'Charlie'] });
});

// POST request
app.post('/users', (req, res) => {
  res.status(201).json({ message: 'User created' });
});

// PUT request
app.put('/users/:id', (req, res) => {
  res.json({ message: `User ${req.params.id} updated` });
});

// DELETE request
app.delete('/users/:id', (req, res) => {
  res.json({ message: `User ${req.params.id} deleted` });
});

// Route with multiple methods
app.route('/products')
  .get((req, res) => res.send('Get all products'))
  .post((req, res) => res.send('Create product'));

app.listen(3000);

Route Parameters & Query Strings

// Route parameters (in URL path)
// GET /users/123
app.get('/users/:id', (req, res) => {
  const userId = req.params.id;
  res.json({ userId });
});

// Multiple parameters
// GET /posts/2024/january
app.get('/posts/:year/:month', (req, res) => {
  const { year, month } = req.params;
  res.json({ year, month });
});

// Query strings (after ?)
// GET /search?q=nodejs&limit=10
app.get('/search', (req, res) => {
  const { q, limit } = req.query;
  res.json({ query: q, limit: limit || 20 });
});

Middleware

Middleware functions have access to the request, response, and the next middleware function. They can execute code, modify req/res, end the request, or call the next middleware.

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

// Built-in middleware for parsing JSON
app.use(express.json());

// Built-in middleware for parsing URL-encoded data
app.use(express.urlencoded({ extended: true }));

// Custom logging middleware
app.use((req, res, next) => {
  console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
  next(); // Pass control to next middleware
});

// Middleware for specific routes
app.use('/api', (req, res, next) => {
  console.log('API request');
  next();
});

// Error handling middleware (4 parameters)
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Something went wrong!' });
});

Handling JSON Data

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

// Parse JSON bodies
app.use(express.json());

// In-memory data store
let users = [
  { id: 1, name: 'Alice', email: 'alice@example.com' },
  { id: 2, name: 'Bob', email: 'bob@example.com' }
];

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

// Get single user
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);
});

// Create user
app.post('/api/users', (req, res) => {
  const { name, email } = req.body;
  
  if (!name || !email) {
    return res.status(400).json({ error: 'Name and email required' });
  }
  
  const newUser = {
    id: users.length + 1,
    name,
    email
  };
  
  users.push(newUser);
  res.status(201).json(newUser);
});

// 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.status(204).send();
});

app.listen(3000);

Serving Static Files

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

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

// With virtual path prefix
app.use('/static', express.static('public'));

// Serve from absolute path
app.use(express.static(path.join(__dirname, 'public')));

// Multiple static directories
app.use(express.static('public'));
app.use(express.static('files'));

app.listen(3000);

Project structure:

my-app/
├── server.js
└── public/
    ├── index.html
    ├── styles.css
    └── images/
        └── logo.png

Router for Modular Routes

// routes/users.js
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.json({ users: [] });
});

router.get('/:id', (req, res) => {
  res.json({ user: { id: req.params.id } });
});

router.post('/', (req, res) => {
  res.status(201).json({ message: 'User created' });
});

module.exports = router;

// server.js
const express = require('express');
const userRoutes = require('./routes/users');

const app = express();

app.use(express.json());
app.use('/api/users', userRoutes);

app.listen(3000);

💡 Key Takeaways

  • • Express simplifies routing with app.get(), app.post(), etc.
  • • Use express.json() middleware to parse JSON request bodies
  • • Access route params with req.params and query strings with req.query
  • • Middleware functions process requests before route handlers
  • • Use express.Router() to organize routes into modules

Continue Learning