Express 5 入门与迁移
本教程共 76 篇 · 第 38 篇 · 更新于 2026-07-25 · 约 5 分钟阅读
38. Express 5 入门与迁移
本节目标:Express 5 最小应用、req/res 对象和 4 到 5 的迁移三大坑。
如果你用原生 http 模块写过 Web 服务,一定体会过那种「什么都得自己拼」的感觉。路由怎么分?POST 数据怎么收?静态文件怎么发?每个问题都要写一堆样板代码。Express 就是来解决这些烦心事的——它像一把瑞士军刀,把 Web 开发里最常见的需求变成了几行配置。
这节我们讲 Express 5,它是目前的稳定版本。网上很多教程还在用 Express 4 的写法,有些在 5 里会直接报错,我会把迁移坑标出来。
安装与最小应用
先初始化项目:
mkdir myapp && cd myapp
npm init -y
npm install express
写一个最小应用,保存为 app.js:
import express from 'express'
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello Express 5')
})
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`)
})
运行:
node app.js
打开浏览器访问 http://localhost:3000,能看到 Hello Express 5。
Note上面的代码用了 ESM(
import)。如果你的package.json没加"type": "module",可以把import改成const express = require('express')。本书默认 ESM-first,但 Express 对两种模块系统都支持。
Express 到底做了什么
我们拿原生 http 模块做个对比。下面这段代码只处理 GET 请求、返回一段文字:
import http from 'http'
const server = http.createServer((req, res) => {
if (req.url === '/' && req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('Hello http')
} else {
res.writeHead(404)
res.end('Not Found')
}
})
server.listen(3000)
代码不算长,但如果要加路由、解析表单、处理文件上传,工作量会成倍增长。Express 的核心价值在于:
- 路由系统:按路径和 HTTP 方法分发请求,代码不再是一堆
if/else - 中间件机制:把「日志记录」「身份校验」「body 解析」这些通用逻辑抽成可复用的插件
- 辅助方法:
res.json()、res.sendFile()这些方法帮你自动设置响应头
请求与响应对象
每个路由回调里都能拿到 req(请求)和 res(响应)两个对象,它们是 Express 对原生对象的包装,加了不少实用属性。
常用的 req 属性:
| 属性 | 含义 |
|---|---|
req.params | 路由参数,如 /users/:id 里的 id |
req.query | 查询字符串,如 ?name=tom |
req.body | POST 请求体(需要 body 解析中间件) |
req.headers | 请求头 |
req.ip | 客户端 IP |
常用的 res 方法:
| 方法 | 作用 |
|---|---|
res.send(data) | 发送字符串、Buffer 或 JSON,自动设 Content-Type |
res.json(obj) | 发送 JSON,自动设 application/json |
res.status(code) | 设置状态码,可链式调用 |
res.redirect(url) | 302 跳转 |
res.sendFile(path) | 发送文件(注意大写 F,Express 5 已移除 res.sendfile) |
示例:
app.get('/user/:id', (req, res) => {
res.status(200).json({
id: req.params.id,
q: req.query.detail
})
})
访问 /user/42?detail=full 会返回 {"id":"42","q":"full"}。
Express 4 到 5 的迁移坑
这是本章重点。网上大量 Express 4 的代码 Copy 到 5 里可能直接起不来,主要变化有三处。
1. 通配符路由语法变了
Express 5 升级了底层的 path-to-regexp,裸写 * 会抛语法错误。
// Express 4 能跑,5 报错
app.all('*', (req, res) => {
res.status(404).send('Not found')
})
// Express 5 正确写法
app.all('/*splat', (req, res) => {
res.status(404).send('Not found')
})
如果你只想捕获未匹配的路由,其实更推荐:
app.use((req, res) => {
res.status(404).send('Not found')
})
2. res.sendfile 被移除
Express 4 里 res.sendfile(小写 f)和 res.sendFile(大写 F)都能用,5 只保留了大写版本。
// Express 4 能跑,5 报错:res.sendfile is not a function
app.get('/file', (req, res) => {
res.sendfile(__dirname + '/notes.txt')
})
// Express 5 正确写法
app.get('/file', (req, res) => {
res.sendFile(__dirname + '/notes.txt')
})
3. 路径中的正则写法收紧
Express 4 允许在路由字符串里直接塞正则,比如 /ab*cd。Express 5 对这类写法更严格,建议改用标准参数或正则对象:
// 不推荐:Express 5 可能表现不一致
app.get('/ab*cd', handler)
// 推荐:用参数或显式正则
app.get('/ab(.*)cd', handler)
Warning如果你维护的是一个 Express 4 的老项目,别急着全局替换。先跑一遍测试,再对照 Express 官方的 Migration Guide 逐项检查。最安全的策略是:先把
*通配和sendfile修掉,这两个是 5 里最常见的启动报错源。
项目结构建议
一个 Express 项目通常按这样组织:
myapp/
├── app.js // 入口,注册中间件和路由
├── routes/
│ ├── index.js
│ └── users.js // 路由拆分
├── controllers/ // 业务逻辑(可选)
├── public/ // 静态资源
├── views/ // 模板文件
└── package.json
入门阶段可以把路由直接写在 app.js 里,等接口多了再拆到 routes/ 目录。下一章我们专门讲路由的各种玩法。