在初学nodejs做API服务器时,我不了解为什么要用express框架的问题,今天想通过这个文章讲清楚express能帮我们省多少事情。
以下是用原生的nodejs,http模块来写一个能提供两个GET接口的服务器。
js
// server.js ------ 零依赖版
const http = require('http');
const PORT = 3001;
const HOST = 'localhost';
// 在 router 函数中添加新的路由处理
function router(req, res) {
// 处理浏览器 favicon 请求,直接返回空
if (req.url === '/favicon.ico') {
res.writeHead(204);
res.end();
return;
}
// 处理 /api/list (保持原有逻辑)
if (req.method === 'GET' && req.url === '/api/list') {
// 1. CORS 响应头(等价于 cors())
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
// 2. 预检 OPTIONS 直接返回 200
if (req.method === 'OPTIONS') {
res.writeHead(200);
res.end();
return;
}
// 3. 返回 JSON
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify({ code: 0, data: ['a', 'b', 'c'] }));
return;
}
// 新增:处理 /goaldata 路径
if (req.method === 'GET' && req.url === '/goaldata') {
// 1. CORS 响应头
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
try {
// 2. 读取 data.json 文件
const fs = require('fs');
const path = require('path');
const dataFilePath = path.join(__dirname, '../data.json');
// 3. 检查文件是否存在
if (fs.existsSync(dataFilePath)) {
const data = fs.readFileSync(dataFilePath, 'utf8');
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(data);
} else {
// 文件不存在时返回空数组
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify([]));
}
} catch (error) {
// 错误处理
res.writeHead(500, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify({ error: '服务器内部错误' }));
}
return;
}
// 其它路径 404
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
}
const server = http.createServer(router);
server.listen(PORT, HOST, () => {
console.log(`API ready on http://${HOST}:${PORT}/goaldata`);
});
以下是采取express框架后的代码:
js
// server.js - Express 版本
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
const PORT = 3001;
const HOST = 'localhost';
// CORS 中间件
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
// 处理 /goaldata 路由
app.get('/goaldata', (req, res) => {
try {
const dataFilePath = path.join(__dirname, '../data.json');
if (fs.existsSync(dataFilePath)) {
const data = fs.readFileSync(dataFilePath, 'utf8');
res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.send(data);
} else {
res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.send(JSON.stringify([]));
}
} catch (error) {
res.status(500).json({ error: '服务器内部错误' });
}
});
// 处理 /api/list 路由
app.get('/api/list', (req, res) => {
res.json({ code: 0, data: ['a', 'b', 'c'] });
});
// 启动服务器
app.listen(PORT, HOST, () => {
console.log(`API ready on http://${HOST}:${PORT}/goaldata`);
});
下面来梳理一下区别: 主要差异点
- 框架引入: 使用 express 替代原生 http 模块
通过 app = express() 创建应用实例 - 路由处理: 使用 app.get() 方法直接定义路由
不需要手动解析 req.url 和 req.method - 中间件机制: 使用 app.use() 统一处理 CORS
通过 next() 传递控制权 - 响应处理: 使用 res.json()、res.send() 等方法简化响应
自动设置 Content-Type 头部 - 错误处理: 使用 res.status().json() 简化状态码和响应体设置
Express 版本代码更简洁,可读性更强,减少了大量手动路由判断的代码。