楼层: 首页/ 软件技术/ Node.js 全栈实战/ Express:最流行的 Web 框架
06

Express:最流行的 Web 框架

Express 4.x / 5.x

上一章那个原生 http 服务器,自己判断 if(req.url === '/') 写不了几行就乱套。Express 就是把这些脏活打包好的框架——你只要说"GET 这个路径时干嘛、POST 那个路径时干嘛",剩下的路由匹配、解析请求体,它全包了。它极简、灵活,是 Node 后端的入门标配(4.x 最稳,5.x 已正式发布)。

十分钟跑起来一个 Express 应用

第一步:初始化并安装

mkdir my-api && cd my-api npm init -y npm i express

第二步:app.js 写个最朴素的接口

import express from "express"; const app = express(); const PORT = 3000; // GET /hello?name=小明 app.get("/hello", (req, res) => { // req.query 就是问号后面的查询参数对象 const name = req.query.name || "朋友"; res.json({ msg: `你好,${name}!欢迎来到 Express。` }); }); app.listen(PORT, () => console.log(`http://localhost:${PORT}`));
$ node app.js http://localhost:3000 # 浏览器或 curl 访问 http://localhost:3000/hello?name=小明

路由:四种 HTTP 动词 + 两种参数

RESTful 风格里,用 HTTP 动词表达"干什么操作",用 URL 表达"对谁干":

动词典型用途例子
GET查数据app.get('/users', ...) 拿用户列表。
POST新建app.post('/users', ...) 新建一个用户。
PUT / PATCH更新app.put('/users/:id', ...) 改某个用户。
DELETE删除app.delete('/users/:id', ...) 删某个用户。

路径参数 :id 和查询参数 req.query 的区别

// /users/123 —— 123 是"路径里的变量",用 :id 占位 app.get("/users/:id", (req, res) => { console.log(req.params.id); // "123" —— 路径参数从 req.params 拿 res.json({ userId: req.params.id }); }); // /search?keyword=node&page=2 —— 问号后面的从 req.query 拿 app.get("/search", (req, res) => { console.log(req.query.keyword, req.query.page); // "node" "2" res.json({ keyword: req.query.keyword }); });

中间件:Express 的灵魂

中间件(Middleware)是"请求到达你的业务代码之前,依次经过的一道道工序"。打个比方:请求是个快递,中间件就是快递从大门到你手上经过的保安(登记)、前台(消毒)、快递柜(扫码)。每道工序干完,调用 next() 放它走,下一道接着处理。

一个打印每个请求日志的全局中间件

// app.use 注册的中间件,每个请求都会先过它 app.use((req, res, next) => { const time = new Date().toISOString(); console.log(`[${time}] ${req.method} ${req.url}`); next(); // 必须调用 next(),不然请求就卡在这,浏览器一直转圈 });

装生产必装的五个中间件

① express.json():解析请求体里的 JSON。没它 req.body 就是 undefined,这是新手第一天必踩的坑。

② express.static('public'):把 public 文件夹变成静态文件目录,图片、CSS、前端页面直接对外。

③ cors:解决跨域。前端网页在 localhost:5173,接口在 localhost:3000,浏览器默认不让跨,装了 cors() 就放行。

④ morgan:自动打印漂亮的请求日志,比手写省事。

⑤ helmet:一键给响应加上一堆安全 HTTP 头,挡掉常见 Web 攻击。

把它们串起来用

import express from "express"; import cors from "cors"; import morgan from "morgan"; import helmet from "helmet"; const app = express(); app.use(helmet()); // 安全头 app.use(cors()); // 跨域放行 app.use(morgan("dev")); // 请求日志 app.use(express.json()); // 解析 JSON 请求体,必须放在路由前面!

把路由拆出去:express.Router

所有路由都写在 app.js 里,三百行后又成大泥球。Router 是"迷你版 app",按功能拆文件:

// routers/users.js —— 用户相关的路由单独放一个文件 import { Router } from "express"; const router = Router(); router.get("/", (req, res) => res.json(["张三", "李四"])); router.get("/:id", (req, res) => res.json({ id: req.params.id })); export default router; // app.js 里挂载:所有 /users 开头的请求交给它管 import userRouter from "./routers/users.js"; app.use("/users", userRouter);

错误处理与 404

// 1. 所有路由都没匹配上 → 404(放在所有路由之后) app.use((req, res) => { res.status(404).json({ error: "接口不存在" }); }); // 2. 全局错误处理中间件:必须四个参数 (err, req, res, next) app.use((err, req, res, next) => { console.error(err.stack); res.status(err.status || 500).json({ error: err.message || "服务器开小差了" }); });
记
本章小结

① Express = 路由(get/post/...)+ 中间件(use)+ 响应(json/send/status)。

② 忘了 express.json() 是第一天必踩的坑,加中间件记得 next(),跨域装 cors。

③ 项目一大就用 Router 按模块拆文件,别把所有路由堆在 app.js。