首页 / Node.js 教程 / Express 5 入门与迁移

Node.js 教程

Express 5 入门与迁移

本教程共 76 篇 · 第 38 篇 · 更新于 2026-07-25 · 约 5 分钟阅读

Node.jsExpressExpress5Web框架迁移

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.bodyPOST 请求体(需要 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/ 目录。下一章我们专门讲路由的各种玩法。