为什么 Express
社区最大、生态最熟、文档最全——第一次写 Node Web 服务首选。
npm install express
Express 5 在 2024 年稳定发布——支持原生 async/await,新项目用 5。
最小服务
import express from 'express';
const app = express();
app.get('/', (req, res) => {
res.send('Hello, Express');
});
app.listen(3000, () => {
console.log('Server on http://localhost:3000');
});
路由
app.get('/users', (req, res) => res.send('list'));
app.get('/users/:id', (req, res) => res.send(`user ${req.params.id}`));
app.post('/users', (req, res) => res.status(201).send('created'));
app.put('/users/:id', ...);
app.delete('/users/:id', ...);
app.patch('/users/:id', ...);
// 一个路径多个方法
app.route('/users')
.get((req, res) => ...)
.post((req, res) => ...);
路由参数
app.get('/users/:id', (req, res) => {
res.send(req.params.id); // /users/42 → '42'
});
app.get('/posts/:year/:month', (req, res) => {
res.send(`${req.params.year}-${req.params.month}`);
});
// 通配
app.get('/files/*', (req, res) => {
res.send(req.params[0]); // /files/a/b/c → 'a/b/c'
});
// 正则
app.get(/\/users\/(\d+)/, (req, res) => {
res.send(req.params[0]);
});
查询参数
// /search?q=hello&page=2
app.get('/search', (req, res) => {
res.send(`${req.query.q}, page ${req.query.page}`);
});
请求体
// 内置中间件
app.use(express.json()); // 解析 JSON body
app.use(express.urlencoded({ extended: true })); // 解析 form
app.post('/users', (req, res) => {
console.log(req.body); // 自动解析的 JSON
res.status(201).json(req.body);
});
响应
res.send('text'); // 文本
res.json({ ok: true }); // JSON(自动 Content-Type)
res.status(404).send('Not Found'); // 状态码
res.redirect('/new-path'); // 302
res.redirect(301, '/permanent'); // 永久重定向
res.sendFile('/path/to/file.pdf'); // 发文件
res.download('/path/to/file.pdf'); // 触发下载
res.cookie('name', 'value'); // 设 cookie
静态文件
app.use(express.static('public'));
// public/css/style.css → http://localhost:3000/css/style.css
app.use('/static', express.static('public')); // 加前缀
// public/css/style.css → /static/css/style.css
路由组(Router)
大型应用拆分路由:
// routes/users.js
import { Router } from 'express';
const router = Router();
router.get('/', (req, res) => res.send('list'));
router.get('/:id', (req, res) => res.send(req.params.id));
router.post('/', (req, res) => res.send('created'));
export default router;
// app.js
import usersRouter from './routes/users.js';
app.use('/users', usersRouter);
模板引擎(如果做 SSR)
npm install ejs
app.set('view engine', 'ejs');
app.set('views', './views');
app.get('/', (req, res) => {
res.render('home', { name: 'Alice' }); // 渲染 views/home.ejs
});
views/home.ejs:
<h1>Hello <%= name %></h1>
错误处理(特殊中间件)
// 4 个参数的中间件 = 错误处理器
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke');
});
// 触发
app.get('/boom', (req, res, next) => {
next(new Error('Boom!')); // 跳到 error handler
});
// Express 5 自动捕获 async 错误
app.get('/async', async (req, res) => {
const data = await someAsync(); // 抛错自动到 error handler
res.json(data);
});
Express 4 需要手动 next(err) 或 express-async-errors 包;Express 5 原生支持。
部署到生产
import express from 'express';
const app = express();
// 信任反向代理(拿真实 IP)
app.set('trust proxy', 1);
// 通用中间件
app.use(express.json({ limit: '1mb' }));
app.use(express.urlencoded({ extended: true, limit: '1mb' }));
// 路由
app.use('/api', apiRouter);
// 错误处理(永远最后)
app.use((err, req, res, next) => {
console.error(err);
res.status(err.status || 500).json({
error: err.message,
});
});
app.listen(process.env.PORT || 3000);
坑
- Express 5 之前不会自动捕获 async 错误——升级到 5 或用
express-async-errors app.use顺序很重要——先注册先生效- 不设
trust proxy→req.ip永远是反代 IP - 大 body 默认拒绝——
express.json({ limit: '10mb' })调整
下一篇:Express 中间件深入。