初始化
创建并启动服务器
const express = require("express"); const app = express(); app.listen(3000, () => console.log("Running on :3000"));
内置中间件
app.use(express.json()); // parse JSON bodies app.use(express.urlencoded({ extended: true })); // form data app.use(express.static("public")); // serve static files
路由
HTTP 方法
app.get("/users", (req, res) => res.json(users)); app.post("/users", (req, res) => res.status(201).json(req.body)); app.put("/users/:id", (req, res) => res.json(updated)); app.delete("/users/:id", (req, res) => res.sendStatus(204));
路由参数
app.get("/users/:id", (req, res) => { const { id } = req.params; res.json({ id }); });
查询字符串
// GET /search?q=express&page=2 app.get("/search", (req, res) => { const { q, page } = req.query; res.json({ q, page }); });
中间件
应用级中间件
app.use((req, res, next) => { console.log(`${req.method} ${req.url}`); next(); });
路由级中间件
const auth = (req, res, next) => { if (!req.headers.authorization) return res.sendStatus(401); next(); }; app.get("/secret", auth, (req, res) => res.json({ ok: true }));
执行顺序
app.use(fn)每次请求都执行(按注册顺序)
app.use(path, fn)仅在匹配路径前缀时执行
next()将控制权传给下一个中间件
next(err)跳转到错误处理器
请求与响应
Request 对象
req.params路由参数(/users/:id
req.query查询字符串(?key=val
req.body解析后的请求体(需解析器)
req.headers请求头对象
req.methodHTTP 方法(GET、POST...)
req.pathURL 路径名
req.cookiesCookie(需 cookie-parser)
Response 对象
res.json(obj)发送 JSON 响应
res.send(body)发送字符串/Buffer/对象
res.status(code)设置 HTTP 状态码(可链式)
res.redirect(url)302 重定向(可传状态码)
res.sendFile(path)将文件作为响应发送
res.sendStatus(code)发送状态码与默认文本
res.set(header, val)设置响应头
错误处理
错误中间件
// Must have 4 parameters — Express recognizes it as error handler app.use((err, req, res, next) => { console.error(err.stack); res.status(err.status || 500).json({ error: err.message }); });

错误处理器必须在所有 app.use() 和路由之后定义

异步错误
// Wrap async route handlers to catch rejections const wrap = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next); app.get("/data", wrap(async (req, res) => { const data = await fetchData(); res.json(data); }));
静态文件
托管静态目录
app.use(express.static("public")); // serves public/style.css at /style.css // With virtual path prefix app.use("/assets", express.static("public")); // serves public/style.css at /assets/style.css
选项
dotfiles'ignore' | 'allow' | 'deny'
maxAgeCache-Control max-age(毫秒)
index索引文件名(默认:index.html
fallthrough404 时传给下一个中间件
模板
视图引擎配置
app.set("view engine", "ejs"); app.set("views", "./views"); app.get("/", (req, res) => { res.render("index", { title: "Home", items: [1, 2, 3] }); });
常用模板引擎
ejs嵌入式 JS 模板(<%= val %>
pug缩进式(前身 Jade)
handlebarsMustache 风格({{val}}
Router
模块化路由
// routes/users.js const router = require("express").Router(); router.get("/", (req, res) => res.json(users)); router.get("/:id", (req, res) => res.json(user)); module.exports = router;
挂载 Router
const usersRouter = require("./routes/users"); app.use("/api/users", usersRouter); // GET /api/users -> router's "/" // GET /api/users/5 -> router's "/:id"
Router 方法
router.get/post/put/deleteHTTP 方法处理器
router.use(fn)Router 级中间件
router.param(name, fn)预处理路由参数
router.route(path)在一个路径上链式注册方法
认证模式
JWT 中间件
const jwt = require("jsonwebtoken"); const auth = (req, res, next) => { const token = req.headers.authorization?.split(" ")[1]; if (!token) return res.sendStatus(401); req.user = jwt.verify(token, process.env.SECRET); next(); };
受保护路由
app.get("/profile", auth, (req, res) => { res.json({ user: req.user }); }); app.use("/api/admin", auth, adminRouter);
常用模式
CORS
const cors = require("cors"); app.use(cors()); // allow all origins app.use(cors({ origin: "https://example.com" })); // restrict
环境与配置
const port = process.env.PORT || 3000; app.listen(port); // Access env in routes if (app.get("env") === "production") { app.use(helmet()); }
常用 npm 包
cors跨域资源共享
helmet安全响应头
morganHTTP 请求日志
cookie-parser解析 Cookie 头
dotenv.env 加载到 process.env
multer多部分表单数据(文件上传)