跳到主要内容

Node.js中间件

介绍

中间件是Node.js应用中的一个核心概念,特别是在Express.js等Web框架中。中间件是一个函数,它可以访问请求对象(req)、响应对象(res)和应用的请求-响应循环中的下一个中间件函数(next)。中间件可以执行各种任务,如日志记录、身份验证、错误处理等。

原理

中间件工作原理

中间件的工作流程:

  1. 当请求到达服务器时,会依次经过所有注册的中间件
  2. 每个中间件可以处理请求、修改请求和响应对象、结束请求-响应循环,或调用下一个中间件
  3. 如果中间件调用next(),则请求会传递给下一个中间件
  4. 如果中间件没有调用next()且没有结束响应,则请求会被挂起

中间件类型

  • 应用级中间件:绑定到app对象的中间件
  • 路由级中间件:绑定到express.Router()对象的中间件
  • 错误处理中间件:带有四个参数(err, req, res, next)的中间件
  • 内置中间件:Express提供的中间件(如express.json())
  • 第三方中间件:由社区提供的中间件(如morgan、cors)

图示

请求 -> 中间件1 -> 中间件2 -> ... -> 路由处理函数 -> 响应
| |
v v
日志记录 身份验证

实例

自定义中间件

// logger.js
const logger = (req, res, next) => {
console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`);
next(); // 调用下一个中间件
};

module.exports = logger;

使用中间件

// app.js
const express = require('express');
const logger = require('./logger');
const app = express();

// 应用级中间件
app.use(logger);
app.use(express.json()); // 内置中间件

// 路由级中间件
const userRouter = express.Router();
userRouter.use((req, res, next) => {
console.log('User router middleware');
next();
});

userRouter.get('/', (req, res) => {
res.json({ message: 'User route' });
});

app.use('/api/users', userRouter);

// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});

// 启动服务器
const port = 3000;
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});

第三方中间件示例

  1. 安装依赖
npm install morgan cors
  1. 使用第三方中间件
// app.js
const express = require('express');
const morgan = require('morgan');
const cors = require('cors');
const app = express();

// 使用morgan记录请求日志
app.use(morgan('dev'));

// 使用cors启用跨域资源共享
app.use(cors());

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

// 启动服务器
const port = 3000;
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});

专业解决方案

常用第三方中间件

  • morgan:HTTP请求日志中间件
  • cors:跨域资源共享中间件
  • helmet:安全中间件,设置各种HTTP头部
  • express-validator:输入验证中间件
  • compression:响应压缩中间件
  • multer:文件上传中间件
  • passport:身份验证中间件

中间件最佳实践

  • 保持中间件简洁,单一职责
  • 按照正确的顺序注册中间件
  • 错误处理中间件应该放在所有路由后面
  • 对于复杂应用,将中间件组织到不同文件中
  • 避免在中间件中进行耗时操作,影响性能
  • 使用next(err)传递错误给错误处理中间件

性能优化

  • 只在需要的路由中使用特定中间件
  • 避免不必要的中间件调用
  • 缓存频繁使用的中间件结果
  • 对于大型应用,考虑使用中间件组合和条件中间件