阿里云主机折上折
  • 微信号
Current Site:Index > Recommended and comparison of commonly used middleware libraries

Recommended and comparison of commonly used middleware libraries

Author:Chuan Chen 阅读数:11119人阅读 分类: Node.js

Recommended and Compared Express Middleware Libraries

Express, as one of the most popular web frameworks for Node.js, relies heavily on middleware for its flexibility and extensibility. Choosing the right middleware can significantly improve development efficiency and project quality. Below is a detailed introduction and comparative analysis of commonly used middleware libraries.

Request Body Parsing Middleware

body-parser

body-parser is a classic middleware in Express for handling HTTP request bodies, supporting JSON, URL-encoded, and text formats.

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

const app = express();

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

app.post('/api/users', (req, res) => {
  console.log(req.body); // Access the parsed request body
  res.send('User created');
});

express.json() and express.urlencoded()

Starting with Express 4.16.0, these two built-in middleware functions were introduced, offering similar functionality to body-parser. The built-in solutions are recommended for basic needs.

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

Comparison:

  • body-parser is a standalone module with more comprehensive features (e.g., text parsing support).
  • Built-in middleware is lighter and suitable for basic requirements.

Static File Serving

serve-static

Express's built-in express.static middleware is based on the serve-static module and is used to serve static files.

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

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

Advanced Configuration Example:

app.use('/static', express.static('public', {
  index: false, // Disable directory indexing
  maxAge: '1d', // Set cache headers
  setHeaders: (res, path) => {
    if (path.endsWith('.gz')) {
      res.set('Content-Encoding', 'gzip');
    }
  }
}));

Session Management

express-session

The most commonly used session management middleware, supporting various storage backends (memory, Redis, MongoDB, etc.).

const session = require('express-session');

app.use(session({
  secret: 'your-secret-key',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: true, maxAge: 3600000 }
}));

app.get('/login', (req, res) => {
  req.session.user = { id: 1, name: 'John' };
  res.send('Logged in');
});

cookie-session

Stores session data directly in client-side cookies, suitable for small session data.

const cookieSession = require('cookie-session');

app.use(cookieSession({
  name: 'session',
  keys: ['key1', 'key2'],
  maxAge: 24 * 60 * 60 * 1000 // 24 hours
}));

Comparison:

  • express-session is suitable for storing large amounts of session data.
  • cookie-session is simpler but limited by cookie size constraints.

Security-Related Middleware

helmet

Enhances application security by setting various HTTP headers.

const helmet = require('helmet');
app.use(helmet());

Custom Configuration:

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "trusted.cdn.com"]
    }
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true
  }
}));

csurf

CSRF protection middleware (Note: This middleware will be removed in Express 5).

const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });

app.get('/form', csrfProtection, (req, res) => {
  res.render('form', { csrfToken: req.csrfToken() });
});

app.post('/process', csrfProtection, (req, res) => {
  // Validate CSRF token
  res.send('Form processed');
});

Logging

morgan

HTTP request logger middleware with support for predefined and custom formats.

const morgan = require('morgan');

// Use predefined format
app.use(morgan('combined'));

// Custom format
app.use(morgan(':method :url :status :res[content-length] - :response-time ms'));

// Log only error requests
app.use(morgan('combined', {
  skip: (req, res) => res.statusCode < 400
}));

winston

A comprehensive logging solution supporting multiple transports and log levels.

const winston = require('winston');
const expressWinston = require('express-winston');

// Request logging
app.use(expressWinston.logger({
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'requests.log' })
  ],
  format: winston.format.combine(
    winston.format.colorize(),
    winston.format.json()
  ),
  meta: true,
  msg: "HTTP {{req.method}} {{req.url}}"
}));

// Error logging
app.use(expressWinston.errorLogger({
  transports: [
    new winston.transports.File({ filename: 'errors.log' })
  ]
}));

Route Management

express.Router

Express's built-in routing system, supporting modular route definitions.

// routes/users.js
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 userRoutes = require('./routes/users');
app.use('/users', userRoutes);

express-promise-router

An enhanced Router that supports asynchronous route handling.

const Router = require('express-promise-router');
const router = new Router();

router.get('/async', async (req, res) => {
  const data = await someAsyncOperation();
  res.json(data);
});

app.use(router);

Error Handling

errorhandler

Error handling middleware for development environments.

const errorHandler = require('errorhandler');

if (process.env.NODE_ENV === 'development') {
  app.use(errorHandler());
}

express-async-errors

Simplifies error handling for asynchronous routes.

require('express-async-errors');

app.get('/async-error', async (req, res) => {
  throw new Error('Something went wrong');
  // No try/catch needed
});

// Global error handler
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).send('Something broke!');
});

Performance Optimization

compression

Response compression middleware supporting gzip/deflate.

const compression = require('compression');

app.use(compression({
  threshold: 1024, // Only compress responses larger than 1KB
  filter: (req, res) => {
    if (req.headers['x-no-compression']) {
      return false;
    }
    return compression.filter(req, res);
  }
}));

express-rate-limit

API request rate-limiting middleware.

const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // Limit each IP to 100 requests
  message: 'Too many requests from this IP, please try again later'
});

app.use('/api/', limiter);

Database Integration

connect-redis

Redis session storage adapter.

const session = require('express-session');
const RedisStore = require('connect-redis')(session);

app.use(session({
  store: new RedisStore({
    host: 'localhost',
    port: 6379,
    ttl: 86400
  }),
  secret: 'your-secret-key',
  resave: false,
  saveUninitialized: false
}));

connect-mongo

MongoDB session storage adapter.

const MongoStore = require('connect-mongo');

app.use(session({
  store: MongoStore.create({
    mongoUrl: 'mongodb://localhost:27017/session_db',
    ttl: 14 * 24 * 60 * 60 // 14 days
  }),
  secret: 'your-secret-key'
}));

File Upload

multer

Handles multipart/form-data form data, primarily used for file uploads.

const multer = require('multer');

// In-memory storage
const upload = multer();

// Disk storage
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'uploads/');
  },
  filename: (req, file, cb) => {
    cb(null, Date.now() + '-' + file.originalname);
  }
});

const upload = multer({ storage });

// Single file upload
app.post('/upload', upload.single('avatar'), (req, res) => {
  console.log(req.file);
  res.send('File uploaded');
});

// Multiple file upload
app.post('/photos', upload.array('photos', 12), (req, res) => {
  console.log(req.files);
  res.send('Files uploaded');
});

API Documentation Generation

swagger-ui-express

Provides Swagger UI for Express applications.

const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));

apidoc

Generates API documentation from code comments.

/**
 * @api {get} /user/:id Get user info
 * @apiName GetUser
 * @apiGroup User
 *
 * @apiParam {Number} id User's unique ID
 *
 * @apiSuccess {String} name Username
 * @apiSuccess {Number} age User age
 */
app.get('/user/:id', (req, res) => {
  // Implementation code
});

Template Engines

express-handlebars

Express integration for Handlebars template engine.

const exphbs = require('express-handlebars');

app.engine('hbs', exphbs({
  extname: '.hbs',
  defaultLayout: 'main',
  layoutsDir: path.join(__dirname, 'views/layouts'),
  partialsDir: path.join(__dirname, 'views/partials')
}));
app.set('view engine', 'hbs');

app.get('/', (req, res) => {
  res.render('home', { title: 'Home Page' });
});

pug

Popular Pug (Jade) template engine.

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

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

Cross-Origin Handling

cors

Middleware for handling Cross-Origin Resource Sharing (CORS).

const cors = require('cors');

// Simple usage
app.use(cors());

// Custom configuration
app.use(cors({
  origin: ['https://example.com', 'https://api.example.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  exposedHeaders: ['X-Custom-Header'],
  credentials: true,
  maxAge: 86400
}));

// Route-level configuration
app.get('/products/:id', cors(), (req, res) => {
  res.json({ id: req.params.id });
});

Testing Related

supertest

Library for testing HTTP endpoints, often used with testing frameworks.

const request = require('supertest');
const app = require('../app');

describe('GET /users', () => {
  it('responds with JSON', (done) => {
    request(app)
      .get('/users')
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200, done);
  });
});

node-mocks-http

Creates mock request and response objects for testing middleware.

const httpMocks = require('node-mocks-http');
const middleware = require('../middleware/logger');

test('logger middleware should log request', () => {
  const req = httpMocks.createRequest({
    method: 'GET',
    url: '/test'
  });
  const res = httpMocks.createResponse();
  const next = jest.fn();

  middleware(req, res, next);

  expect(next).toHaveBeenCalled();
});

Utility Tools

express-validator

Request data validation middleware.

const { body, validationResult } = require('express-validator');

app.post('/user', 
  body('username').isLength({ min: 5 }).trim().escape(),
  body('email').isEmail().normalizeEmail(),
  body('age').isInt({ min: 18 }),
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    // Process valid data
    res.send('User created');
  }
);

express-list-endpoints

Lists all registered routes in an application.

const listEndpoints = require('express-list-endpoints');

// Get all routes
const allRoutes = listEndpoints(app);
console.log(allRoutes);

// Example output:
// [
//   { path: '/', methods: ['GET'] },
//   { path: '/users', methods: ['GET', 'POST'] }
// ]

Microservices Related

express-gateway

Framework for building API gateways.

// gateway.config.yml
http:
  port: 8080
apiEndpoints:
  api:
    host: localhost
    paths: '/ip'
serviceEndpoints:
  httpbin:
    url: 'https://httpbin.org'
policies:
  - proxy
pipelines:
  default:
    apiEndpoints:
      - api
    policies:
      - proxy:
          - action:
              serviceEndpoint: httpbin
              changeOrigin: true

express-http-proxy

HTTP proxy middleware.

const proxy = require('express-http-proxy');

app.use('/proxy', proxy('http://example.com', {
  proxyReqPathResolver: (req) => {
    return req.url;
  },
  userResDecorator: (proxyRes, proxyResData, userReq, userRes) => {
    const data = JSON.parse(proxyResData.toString());
    data.customField = 'proxied';
    return JSON.stringify(data);
  }
}));

Real-Time Communication

express-ws

Adds WebSocket support to Express.

const expressWs = require('express-ws')(app);

app.ws('/echo', (ws, req) => {
  ws.on('message', (msg) => {
    ws.send(msg);
  });
});

// Supports both HTTP and WebSocket
app.get('/echo', (req, res) => {
  res.send('Use WebSocket endpoint');
});

socket.io

Popular real-time communication library with good Express integration.

const http = require('http');
const socketIo = require('socket.io');

const server = http.createServer(app);
const io = socketIo(server);

io.on('connection', (socket) => {
  console.log('New client connected');
  
  socket.on('chat message', (msg) => {
    io.emit('chat message', msg);
  });

  socket.on('disconnect', () => {
    console.log('Client disconnected');
  });
});

server.listen(3000);

Internationalization

i18next-express-middleware

Internationalization (i18n) middleware.

const i18next = require('i18next');
const i18nextMiddleware = require('i18next-express-middleware');

i18next
  .use(i18nextMiddleware.LanguageDetector)
  .init({
    fallbackLng: 'en',
    resources: {
      en: { translation: require('./locales/en.json') },
      zh: { translation: require('./locales/zh.json') }
    }
  });

app.use(i18nextMiddleware.handle(i18next));

app.get('/', (req, res) => {
  res.send(req.t('welcome_message'));
});

Monitoring and Metrics

express-status-monitor

Real-time application monitoring dashboard.

const expressStatusMonitor = require('express-status-monitor');

app.use(expressStatusMonitor({
  path: '/status',
  spans: [
    { interval: 1, retention: 60 }, // 1-minute sampling, retain 60 data points
    { interval: 5, retention: 60 },
    { interval: 15, retention: 60 }
  ],
  chartVisibility: {
    cpu: true,
    mem: true,
    load: true,
    responseTime: true,
    rps: true,
    statusCodes: true
  }
}));

prom-client

Prometheus metrics collection.

const promBundle = require('express-prom-bundle');
const metricsMiddleware = promBundle({
  includeMethod: true,
  includePath: true,
  customLabels: { project_name: 'hello_world' },
  promClient: {
    collectDefaultMetrics: {
      timeout: 1000
    }
  }
});

app.use(metricsMiddleware);

// Expose metrics endpoint
app.get('/metrics', (req, res) => {
  res.set('Content-Type', promBundle.register.contentType);
  res.end(promBundle.register.metrics());
});

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.