原生 Node.js HTTP Server 实现分析
核心概念
-
请求处理流程
- 使用
http.createServer()创建服务器实例 - 通过回调函数处理每个请求
- 手动解析 URL 和请求方法
- 手动设置响应头和状态码
- 使用
-
路由实现
const controllers: Record<string, Controller> = { '/': (req: Request, res: Response) => { const data = services['/']({ name: 'word' }) res.end(data) }, // ... 其他路由 }- 使用对象映射实现路由
- 需要手动处理 404 情况
- 路由处理逻辑与业务逻辑分离
-
中间件机制
- 原生实现中没有内置中间件机制
- 需要手动实现请求处理管道
- 每个中间件需要显式调用 next()
优点
- 轻量级,无额外依赖
- 完全控制请求处理流程
- 性能开销最小
- 适合学习 HTTP 协议原理
缺点
- 需要手动处理很多底层细节
- 代码结构可能变得复杂
- 缺乏内置功能(如路由、中间件等)
- 需要自行实现错误处理
Express.js 实现分析
核心概念
-
中间件系统
- 使用
app.use()注册中间件 - 自动处理 next() 调用
- 支持异步中间件
- 可以访问和修改请求/响应对象
- 使用
-
常用中间件集成
// body-parser 中间件 app.use(express.json()) // 处理 JSON 请求体 app.use(express.urlencoded({ extended: true })) // 处理 URL 编码的请求体 // CORS 中间件 app.use(cors({ origin: 'http://localhost:3000', methods: ['GET', 'POST'], allowedHeaders: ['Content-Type'] }))body-parser 原理
-
请求体解析流程
- 接收原始请求数据流
- 根据 Content-Type 选择解析方式
- 将数据流转换为 JavaScript 对象
- 挂载到 req.body 供后续中间件使用
-
原生实现对比
// 原生 Node.js 实现 let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', () => { const data = JSON.parse(body); // 处理数据... }); -
应用场景
- 表单提交处理
// 处理 application/x-www-form-urlencoded 格式 app.use(express.urlencoded({ extended: true })); // 前端表单提交 // <form method="POST" action="/submit"> // <input name="username" value="john"> // <input name="password" value="123456"> // </form>- JSON API 开发
// 处理 application/json 格式 app.use(express.json()); // 前端 AJAX 请求 // fetch('/api/users', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify({ name: 'John', age: 30 }) // });- 文件上传处理
// 处理 multipart/form-data 格式 const multer = require('multer'); const upload = multer({ dest: 'uploads/' }); app.post('/upload', upload.single('file'), (req, res) => { console.log(req.file); // 文件信息 console.log(req.body); // 其他表单字段 });- RESTful API 开发
// 处理复杂的 API 请求体 app.post('/api/products', express.json(), (req, res) => { const { name, price, category, tags } = req.body; // 处理产品创建逻辑 });- Webhook 集成
// 处理第三方服务的回调数据 app.post('/webhook', express.json(), (req, res) => { const { event, data, signature } = req.body; // 验证签名并处理事件 });
CORS 原理
- 跨域资源共享机制
- 浏览器发送预检请求(OPTIONS)
- 服务器返回允许的源、方法和头部
- 浏览器根据响应决定是否允许实际请求
- 关键响应头
// 原生 Node.js 实现 res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
-
-
路由系统
app.get('/', (req, res) => { res.send('Hello World') })- 内置路由系统
- 支持路由参数
- 支持路由分组
- 自动处理 404
-
请求处理
- 自动解析请求体
- 内置静态文件服务
- 支持模板引擎
- 内置错误处理
优点
- 丰富的生态系统
- 简洁的 API 设计
- 内置常用功能
- 易于扩展和维护
缺点
- 额外的性能开销
- 可能过度封装
- 学习曲线相对较陡
- 依赖第三方中间件
使用场景建议
适合使用原生 Node.js HTTP Server 的场景
- 学习 HTTP 协议原理
- 构建简单的 API 服务
- 对性能要求极高的场景
- 需要完全控制请求处理流程
适合使用 Express.js 的场景
- 快速开发 Web 应用
- 构建复杂的 API 服务
- 需要丰富的中间件支持
- 团队协作开发
总结
选择使用原生 Node.js HTTP Server 还是 Express.js,主要取决于项目需求:
- 如果追求性能和完全控制,选择原生实现
- 如果追求开发效率和功能丰富,选择 Express.js
理解两者的区别和实现原理,有助于我们更好地选择和使用合适的工具。