Skip to main content
  1. Posts/

Express Complete Guide: The Classic Node.js Web Framework

sun.ao
Author
sun.ao
I’m sun.ao, a programmer passionate about technology, focusing on AI and digital transformation.
Table of Contents

If Node.js is the “founding father” of JavaScript on the server, then Express is the “pioneer” of Node.js web frameworks. Although many frameworks have emerged since, Express remains the top choice for Node.js developers.

What is Express?
#

Express is the most classic web framework in the Node.js ecosystem, created by TJ Holowaychuk in 2009. Its core characteristic is: simple, flexible, minimalist.

Understanding Through Analogy
#

AspectExpressNestJS
StyleMinimalistEnterprise
ConstraintsAlmost noneConvention first
Learning curveFlatRelatively steep
FlexibilityExtremely highMedium
LikeLEGO free-form buildingLEGO official set

Express gives you maximum freedom—you can organize code your own way.

Core Features
#

1. Simple API: Five Minutes to Get Started
#

Express’s API is extremely simple:

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

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

app.get('/api/users', (req, res) => {
  res.json([
    { id: 1, name: 'John' },
    { id: 2, name: 'Jane' }
  ]);
});

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

2. Routing System: Clear and Intuitive
#

Express’s routing is very intuitive:

// Basic routes
app.get('/users', (req, res) => {
  res.send('Get user list');
});

app.post('/users', (req, res) => {
  res.send('Create user');
});

app.put('/users/:id', (req, res) => {
  res.send(`Update user ${req.params.id}`);
});

app.delete('/users/:id', (req, res) => {
  res.send(`Delete user ${req.params.id}`);
});

// Route parameters
app.get('/users/:id/posts/:postId', (req, res) => {
  res.json({
    userId: req.params.id,
    postId: req.params.postId
  });
});

// Query parameters
app.get('/search', (req, res) => {
  res.json(req.query);  // ?q=keyword&page=1
});

3. Middleware: The Soul of Express
#

Middleware is the core concept of Express—a function that has access to request and response objects.

// Middleware function
const logger = (req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next();  // Call the next middleware
};

// Application-level middleware
app.use(logger);

// Route-level middleware
const auth = (req, res, next) => {
  if (req.headers.authorization) {
    next();
  } else {
    res.status(401).send('Unauthorized');
  }
};

app.get('/protected', auth, (req, res) => {
  res.send('Protected route');
});

Common middleware:

const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const bodyParser = require('body-parser');

app.use(cors());           // Cross-origin resource sharing
app.use(helmet());         // Security headers
app.use(morgan('dev'));    // Logging
app.use(bodyParser.json()); // Parse JSON
app.use(bodyParser.urlencoded({ extended: true })); // Parse form data

4. Request Object: Getting Client Data
#

app.get('/demo', (req, res) => {
  // Route parameters: /demo/123
  console.log(req.params.id);

  // Query parameters: /demo?id=123
  console.log(req.query.id);

  // Request headers
  console.log(req.headers.authorization);

  // Request body (needs body-parser)
  console.log(req.body.name);

  // Cookies
  console.log(req.cookies.token);
});

5. Response Object: Returning Data
#

app.get('/responses', (req, res) => {
  // Send string
  res.send('Hello');

  // Send JSON
  res.json({ message: 'Hello' });

  // Send file
  res.download('/path/to/file');

  // Redirect
  res.redirect('/other-page');

  // Set status code
  res.status(201).json({ created: true });
});

6. Error Handling
#

// Synchronous error handling
app.get('/error', (req, res) => {
  throw new Error('Something went wrong!');
});

// Asynchronous error handling
app.get('/async-error', async (req, res, next) => {
  try {
    const data = await fetchData();
    res.json(data);
  } catch (error) {
    next(error);  // Pass to error handling middleware
  }
});

// Error handling middleware (must be at the end)
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Server error' });
});

7. Router: Modularizing Routes
#

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

router.get('/', (req, res) => {
  res.send('User list');
});

router.get('/:id', (req, res) => {
  res.send(`User ${req.params.id}`);
});

module.exports = router;

// app.js
const usersRouter = require('./users');
app.use('/users', usersRouter);

Why is Express So Popular?#

1. Simple and Flexible
#

Express’s design philosophy is “minimalism”:

  • Core is very small
  • Features extend through middleware
  • No forced code structure

2. Mature Ecosystem
#

Express has the most mature Node.js ecosystem:

  • Rich middleware
  • Complete documentation
  • Large community
  • Many tutorials

3. Foundation for Most Node.js Frameworks
#

Many frameworks are built on Express:

  • NestJS (can use Express adapter)
  • Next.js (early versions)
  • Feathers
  • Sails.js

4. Perfect for Rapid Development
#

For small projects and prototypes, Express is the best choice:

  • Quick to learn
  • Less code
  • High flexibility

Use Cases
#

ScenarioSuitabilityNotes
Small web apps⭐⭐⭐⭐⭐Simple and flexible
REST API⭐⭐⭐⭐⭐Fast development
Prototyping⭐⭐⭐⭐⭐Rapid iteration
Microservices⭐⭐⭐⭐Lightweight and fast
Medium-large apps⭐⭐⭐Needs good code organization
Enterprise apps⭐⭐NestJS recommended

Express vs Native Node.js
#

// Native Node.js
const http = require('http');
const server = http.createServer((req, res) => {
  if (req.url === '/users' && req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify([{ id: 1 }]));
  }
});
server.listen(3000);

// Express
const express = require('express');
const app = express();
app.get('/users', (req, res) => {
  res.json([{ id: 1 }]);
});
app.listen(3000);

Express greatly simplifies Node.js HTTP handling.

Learning Path
#

Beginner (1 week)
#

  1. Master Node.js basics
  2. Understand Express basics
  3. Learn routing and middleware
  4. Master request and response objects

Intermediate (1-2 weeks)
#

  1. Deep dive into middleware principles
  2. Master error handling
  3. Learn to use Router for modularization
  4. Master template engines (optional)

Advanced (continuous learning)
#

  1. Performance optimization
  2. Security best practices
  3. Database integration
  4. Understand Express internals

Common Middleware
#

MiddlewarePurpose
corsCross-origin support
helmetSecurity headers
morganLogging
body-parserRequest body parsing
cookie-parserCookie parsing
express-sessionSessions
multerFile uploads
compressionCompression

Comparison with Other Node.js Frameworks
#

FeatureExpressKoaFastifyNestJS
Simplicity⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Performance⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Async supportCallbacksasync/awaitasync/awaitasync/await
MiddlewareTraditionalOnion modelPluginsGuards/interceptors
Learning curveFlatFlatFlatRelatively steep

Simply put:

  • Express: Classic and stable, mature ecosystem
  • Koa: More modern, onion model
  • Fastify: Highest performance
  • NestJS: Enterprise architecture

Summary
#

Express is the “evergreen tree” of the Node.js ecosystem:

  1. Simple API—Five minutes to get started
  2. Middleware system—Flexible extensions
  3. Clear routing—Easy to understand
  4. Mature ecosystem—Abundant resources
  5. Highly flexible—Customize as needed

Although “new frameworks” keep emerging, Express remains the foundation of Node.js development. Once you learn Express, you can easily transition to other frameworks.


Next up: We’ve covered backend frameworks. Now let’s move to mobile development. Flutter is Google’s cross-platform UI framework, known for high-performance rendering and “write once, run anywhere.” Let’s dive into this “new species of UI frameworks” in the next article.

Related articles