
Express.js is a minimal and flexible web application framework for NodeJs. Think of it as a layer on top of NodeJs that makes building web servers and API much easier and faster than using vanilla NodeJs.
While NodeJs gives us the capability to create HTTP servers, doing everything manually can be quite tedious. Express.js provides a set of tools and features that simplify common web development tasks like:
My takeaway: Express.js is to NodeJs what React is to JavaScript - it makes development faster and more organized!
Let me show you the difference with a simple example.
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
const pathname = url.parse(req.url).pathname;
const method = req.method;
// Set headers manually
res.setHeader('Content-Type', 'application/json');
// Handle different routes manually
if (pathname === '/' && method === 'GET') {
res.statusCode = 200;
res.end(JSON.stringify({ message: 'Home page' }));
} else if (pathname === '/users' && method === 'GET') {
res.statusCode = 200;
res.end(JSON.stringify({ users: ['John', 'Jane'] }));
} else if (pathname === '/users' && method === 'POST') {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
// Parse and handle POST data
res.statusCode = 201;
res.end(JSON.stringify({ message: 'User created' }));
});
} else {
res.statusCode = 404;
res.end(JSON.stringify({ error: 'Not found' }));
}
});
server.listen(3000, () => {
console.log('Server running on port 3000');
});
const express = require('express');
const app = express();
// Middleware to parse JSON automatically
app.use(express.json());
// Clean and simple routing
app.get('/', (req, res) => {
res.json({ message: 'Home page' });
});
app.get('/users', (req, res) => {
res.json({ users: ['John', 'Jane'] });
});
app.post('/users', (req, res) => {
// req.body is automatically parsed
res.status(201).json({ message: 'User created' });
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
See the difference? Express.js reduces the code by 70% and makes it much more readable!
Express provides an intuitive way to handle different HTTP methods and URL patterns:
// Different HTTP methods
app.get('/users', getAllUsers);
app.post('/users', createUser);
app.put('/users/:id', updateUser);
app.delete('/users/:id', deleteUser);
// Route parameters
app.get('/users/:id', (req, res) => {
const userId = req.params.id;
res.json({ userId });
});
// Query parameters automatically parsed
app.get('/search', (req, res) => {
const { q, limit } = req.query; // ?q=nodejs&limit=10
res.json({ query: q, limit });
});
Middleware functions execute during the request-response cycle:
// Application-level middleware (runs for every request)
app.use((req, res, next) => {
console.log(`${req.method} ${req.path} - ${new Date()}`);
next(); // Pass control to next middleware
});
// Route-specific middleware
app.get('/protected', authenticateUser, (req, res) => {
res.json({ message: 'Protected content' });
});
function authenticateUser(req, res, next) {
// Check authentication
if (req.headers.authorization) {
next(); // User is authenticated, continue
} else {
res.status(401).json({ error: 'Unauthorized' });
}
}
Express comes with useful built-in middleware:
// Parse JSON bodies
app.use(express.json());
// Parse URL-encoded bodies (form data)
app.use(express.urlencoded({ extended: true }));
// Serve static files
app.use(express.static('public'));
Easily render dynamic HTML:
app.set('view engine', 'ejs');
app.get('/profile/:name', (req, res) => {
res.render('profile', {
username: req.params.name,
title: 'User Profile'
});
});
Understanding how Express handles requests is crucial:
1. Client Request →
2. Express App →
3. Middleware Stack →
4. Route Handler →
5. Response →
6. Client
Here's a practical example:
const express = require('express');
const app = express();
// 1. Logger middleware (runs first)
app.use((req, res, next) => {
console.log('🚀 Request received:', req.method, req.path);
next();
});
// 2. JSON parser middleware
app.use(express.json());
// 3. Authentication middleware (conditional)
const authMiddleware = (req, res, next) => {
if (req.path.startsWith('/api/protected')) {
// Check for auth token
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
}
next();
};
app.use(authMiddleware);
// 4. Route handlers
app.get('/api/public', (req, res) => {
res.json({ message: 'This is public' });
});
app.get('/api/protected/data', (req, res) => {
res.json({ data: 'This is protected data' });
});
// 5. Error handling middleware (runs last)
app.use((err, req, res, next) => {
console.error('❌ Error:', err.message);
res.status(500).json({ error: 'Something went wrong!' });
});
app.listen(3000, () => {
console.log('✅ Server running on http://localhost:3000');
});
As your Express app grows, organize it properly:
my-express-app/
├── app.js # Main application file
├── package.json # Dependencies
├── routes/ # Route handlers
│ ├── index.js
│ ├── users.js
│ └── auth.js
├── middleware/ # Custom middleware
│ ├── auth.js
│ └── logger.js
├── controllers/ # Business logic
│ ├── userController.js
│ └── authController.js
├── models/ # Database models
│ └── User.js
├── utils/ # Utility functions
│ └── helpers.js
├── public/ # Static files
│ ├── css/
│ ├── js/
│ └── images/
└── views/ # Template files
├── index.ejs
└── profile.ejs
// routes/users.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.json({ users: [] });
});
router.post('/', (req, res) => {
res.json({ message: 'User created' });
});
module.exports = router;
// app.js
const userRoutes = require('./routes/users');
app.use('/api/users', userRoutes);
// controllers/userController.js
const userController = {
getAllUsers: (req, res) => {
// Business logic here
res.json({ users: [] });
},
createUser: (req, res) => {
// Business logic here
res.status(201).json({ message: 'User created' });
}
};
module.exports = userController;
// routes/users.js
const { getAllUsers, createUser } = require('../controllers/userController');
router.get('/', getAllUsers);
router.post('/', createUser);
And that's my introduction to Express.js! 🚀
I'm Rahul Aher, and these are my learning notes on NodeJs. If you find these notes helpful, please share them with your friends. If you spot any errors or have improvements, feel free to contribute by forking the repo. Let's learn together! Also, please consider giving a star ⭐ to this repo. For any queries, let's connect here.
Take care, see you in the next lesson! 😊

I'm Rahul, Sr. Software Engineer (SDE II) and passionate content creator. Sharing my expertise in software development to assist learners.
More about me