1. 中间件概念与Express入门

说实话,我刚开始接触Node.js那会儿,对「中间件」这个词挺懵的。听着高大上,其实说白了,它就是一层一层的处理函数。你发一个请求过来,经过一层层中间件的加工,最后返回响应。就这么简单。

我在项目中见过不少新手,一上来就写几百行的路由处理函数。结果呢?代码耦合严重,改一个地方崩一片。中间件就是来解决这个问题的。

中间件的定义

中间件是什么?我习惯这么理解:它是请求-响应周期中的一个处理单元。每个中间件都能访问请求对象、响应对象,以及下一个中间件函数。

一个典型的中间件长这样:

function myMiddleware(req, res, next) {
  // 你可以在这里做任何事
  console.log('请求来了:', req.method, req.url);
  
  // 记得调用 next(),否则请求会卡住
  next();
}

嗯,这里要注意:next() 是关键。你不调用它,请求就停在这儿了,后面的中间件永远跑不到。我曾经在调试一个线上问题时,花了整整两个小时才发现是某个中间件忘了调 next()

核心要点:中间件就是一个函数,它要么结束请求(返回响应),要么把控制权交给下一个中间件。

Express框架简介

Express 是目前Node.js生态里最流行的Web框架。为什么选它?我个人觉得有几点:

  • 轻量灵活——核心功能就那些,其他靠中间件扩展
  • 社区庞大——你想到的中间件,基本都有人写好了
  • 学习曲线平缓——半天就能上手,一周就能写出像样的应用

你想想看,一个框架能活这么多年,肯定有它的道理。Express 的设计哲学就是「小而美」,它只做一件事——处理HTTP请求,而且做得很好。

第一个Express应用

咱们直接上手。先装包:

npm init -y
npm install express

然后写一个最简单的应用:

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(3000, () => {
  console.log('服务器跑在 http://localhost:3000');
});

就这么几行,一个Web服务器就跑起来了。你访问 http://localhost:3000,就能看到「Hello World!」。

小技巧:我习惯用 nodemon 来启动开发环境,这样改代码后自动重启,省得手动按 Ctrl+C。

中间件执行流程

这是重点。中间件的执行顺序,说白了就是先进先出。你注册中间件的顺序,决定了它们执行的顺序。

看个例子:

const express = require('express');
const app = express();

// 中间件1:记录日志
app.use((req, res, next) => {
  console.log('1. 日志中间件');
  next();
});

// 中间件2:解析请求体
app.use((req, res, next) => {
  console.log('2. 解析中间件');
  next();
});

// 中间件3:处理路由
app.get('/', (req, res) => {
  console.log('3. 路由处理');
  res.send('完成');
});

app.listen(3000);

当你访问 / 时,控制台会依次输出:

1. 日志中间件
2. 解析中间件
3. 路由处理

为什么会这样?因为Express内部维护了一个中间件队列。每个请求进来,就从队列头开始,一个个执行。每个中间件调 next(),就跳到下一个。不调,就停住。

避坑指南:我曾经犯过一个错误——把路由处理写在中间件前面。结果路由先匹配了,直接返回响应,后面的中间件根本没机会执行。记住:中间件的顺序就是执行顺序

还有一种情况,中间件可以提前结束请求:

app.use((req, res, next) => {
  if (!req.headers.authorization) {
    return res.status(401).send('没权限');
  }
  next();
});

这里如果没带认证头,中间件直接返回401,后面的路由根本不会执行。这就是中间件的威力——你可以在请求到达业务逻辑之前,做各种前置检查。

中间件的类型

Express里有几种中间件,我简单列一下:

类型 说明 示例
应用级中间件 绑定到 app 实例上 app.use()
路由级中间件 绑定到 router 实例上 router.use()
错误处理中间件 有4个参数 (err, req, res, next)
内置中间件 Express自带的 express.json()
第三方中间件 社区提供的 cors, morgan

我个人最常用的是应用级中间件和第三方中间件。比如 cors 解决跨域,morgan 记录请求日志,express.json() 解析JSON请求体。这些现成的中间件,能帮你省下大量时间。

小结

这一章我们聊了中间件的概念、Express的入门、第一个应用,以及中间件的执行流程。说白了,中间件就是一层层的处理函数,按顺序执行,每个函数都能决定是继续往下走,还是直接返回。

下一章我们会深入中间件的实现原理,看看Express内部是怎么管理这些中间件的。到时候我会分享一些我在源码阅读中的心得,挺有意思的。