Node.js 主流框架对比
Express.js / Koa.js / Nest.js / Next.js / Fastify
Express.js
简介
Express.js 是 Node.js 生态系统中最流行、最成熟的 Web 框架。自 2010 年发布以来,已成为 Node.js Web 开发的标准化框架。
实现原理
核心特性
- 简洁的中间件架构 :使用
app.use()注册中间件 - 路由系统:基于 HTTP 方法和 URL 路径进行路由分发
- 静态资源服务 :
express.static()提供静态文件服务
中间件机制
javascript
// Express 中间件执行流程
app.use((req, res, next) => {
// 执行逻辑
next(); // 调用下一个中间件
});
Express 使用同步式中间件链 ,通过回调函数 next() 来控制请求流程。中间件按照注册顺序执行。
路由系统
- 使用路由表(Route Table)存储路由规则
- 通过正则表达式匹配 URL 路径
- 支持参数路由和通配符
性能表现
指标
- 吞吐量:中等
- 延迟:较中等
- 内存占用:中等
- 初始化速度:快
性能特点
- 优势:成熟稳定,生态系统完善
- 劣势:性能不是最优,相比 Fastify 和 Koa 略慢
基准测试(RPS - Requests Per Second)
- 简单 JSON 响应:~15,000 RPS
- 数据库查询:取决于数据库性能
适用场景
理想场景
- 传统 Web 应用:企业级应用、后台管理系统
- RESTful API:中等规模的 API 服务
- 快速原型开发:需要快速搭建项目
- 学习和教学:最广泛的教程资源
- 中小型项目:不需要极高性能的场景
不适用场景
- 极高并发需求(每秒数十万请求)
- 需要极致性能优化的场景
项目结构示例
express-demo/
├── package.json
├── app.js
├── routes/
│ └── users.js
└── middleware/
└── logger.js
-
app.js: 入口,注册中间件与路由
-
routes/users.js: 用户相关路由
-
middleware/logger.js: 简单请求日志中间件
快速开始
npm init -y
npm i express
node app.js
代码示例
javascript
const express = require('express');
const app = express();
// 中间件
app.use(express.json());
// 路由
app.get('/api/users', (req, res) => {
res.json({ users: [] });
});
// 错误处理
app.use((err, req, res, next) => {
res.status(500).json({ error: err.message });
});
app.listen(3000);
核心结构示例:Express
javascript
const express = require('express');
const app = express();
// 1) 全局中间件
app.use(express.json());
// 2) 路由层(按资源组织)
const router = express.Router();
router.get('/users', (req, res) => res.json([]));
router.post('/users', (req, res) => res.status(201).json(req.body));
app.use('/api', router);
// 3) 404 兜底
app.use((req, res) => res.status(404).json({ error: 'Not Found' }));
// 4) 错误处理中间件
app.use((err, req, res, next) => res.status(500).json({ error: err.message }));
Koa.js
简介
Koa.js 由 Express.js 的原班人马(TJ Holowaychuk)在 2013 年创建,是下一代 Node.js Web 框架。采用全新的设计理念,基于 async/await 和生成器函数。
实现原理
核心特性
- 洋葱模型(Onion Model):中间件按级联方式组织
- 异步控制:原生支持 async/await,无需回调
- 轻量级:核心功能极简,依赖社区中间件
- 错误处理:采用 try/catch 机制
洋葱模型
javascript
// 请求流程:A -> B -> C -> ... -> Handler -> ... -> C -> B -> A
app.use(async (ctx, next) => {
console.log(1);
await next();
console.log(4);
});
app.use(async (ctx, next) => {
console.log(2);
await next();
console.log(3);
});
// 输出:1 2 3 4
Koa 使用 递归式上下文传递 ,通过 await next() 实现中间件的前后执行。
上下文对象(Context)
ctx.request:请求对象ctx.response:响应对象ctx.state:状态存储ctx.throw():抛出错误
性能表现
指标
- 吞吐量:优秀(相比 Express 提升约 30-40%)
- 延迟:较低
- 内存占用:较低(核心库极简)
- 初始化速度:快
性能特点
- 优势:异步性能优秀,内存占用低,代码更优雅
- 劣势:无法兼容 Express 中间件(API 设计不同)
基准测试
- 简单 JSON 响应:~20,000-25,000 RPS
- 异步操作处理性能显著优于 Express
适用场景
理想场景
- 现代异步应用:大量使用 async/await 的项目
- API 网关:需要复杂中间件处理逻辑
- 微服务架构:轻量级、高性能需求
- 需要精细控制的场景:使用洋葱模型处理请求/响应
- 高性能 API:追求更好的性能表现
不适用场景
- 需要直接使用 Express 中间件的项目
- 完全同步、简单的应用场景
项目结构示例
koa-demo/
├── package.json
├── app.js
├── router/
│ └── index.js
└── middleware/
└── timer.js
-
app.js: 入口,注册中间件与路由
-
router/index.js : 使用
@koa/router定义路由 -
middleware/timer.js: 计算响应时间
快速开始
npm init -y
npm i koa @koa/router
node app.js
代码示例
javascript
const Koa = require('koa');
const app = new Koa();
// 异步中间件
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
ctx.set('X-Response-Time', `${ms}ms`);
});
app.use(async (ctx) => {
ctx.body = { message: 'Hello Koa' };
});
app.listen(3000);
核心结构示例:Koa
javascript
const Koa = require('koa');
const Router = require('@koa/router');
const app = new Koa();
const router = new Router();
// 1) 中间件(洋葱模型)
app.use(async (ctx, next) => { await next(); });
// 2) 路由层
router.get('/users', (ctx) => { ctx.body = []; });
router.post('/users', (ctx) => { ctx.status = 201; ctx.body = {}; });
app.use(router.routes()).use(router.allowedMethods());
// 3) 404 与错误处理
app.use((ctx) => { ctx.status = 404; ctx.body = { error: 'Not Found' }; });
app.on('error', (err) => console.error(err));
Nest.js
简介
Nest.js 是构建在 Express 和 Fastify 之上的企业级 Node.js 框架。受 Angular 启发,采用模块化、依赖注入、装饰器等概念,为大型应用提供完整的架构支持。
实现原理
核心特性
- 模块化架构:模块(Module)作为应用的基本单元
- 依赖注入(DI):自动管理组件依赖关系
- 装饰器模式:使用 TypeScript 装饰器定义路由、中间件等
- 提供者(Provider):服务、控制器、中间件等核心概念
- TypeScript 优先:完全基于 TypeScript 构建
架构层次
Application
├── Module(模块)
│ ├── Controller(控制器)
│ ├── Service(服务)
│ └── Provider(提供者)
└── Middleware(中间件)
依赖注入系统
typescript
// 服务定义
@Injectable()
export class UsersService {
findOne(id: string) {
return { id };
}
}
// 控制器注入服务
@Controller('users')
export class UsersController {
constructor(private usersService: UsersService) {}
@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(id);
}
}
性能表现
指标
- 吞吐量:优秀(基于 Express 或 Fastify 适配器)
- 延迟:取决于底层框架
- 内存占用:较高(框架功能完整)
- 初始化速度:较慢(需要编译 TypeScript,初始化 DI 容器)
性能特点
- 优势:使用 Fastify 适配器时性能卓越;架构清晰,易于维护
- 劣势:初始学习曲线陡峭;框架重量级
基准测试
- 使用 Express 适配器:与 Express 相当
- 使用 Fastify 适配器:接近 Fastify 性能
- 复杂应用:优于传统架构(得益于模块化和依赖注入)
适用场景
理想场景
- 大型企业应用:需要清晰的架构和可维护性
- TypeScript 项目:完全基于 TypeScript
- 团队协作:多人开发,需要标准化架构
- 微服务架构:内置微服务支持
- 需要依赖注入:复杂的业务逻辑和依赖关系
- 从 Angular 迁移:前端团队熟悉的架构模式
不适用场景
- 小型简单项目(杀鸡用牛刀)
- 不需要 TypeScript 的项目
- 追求最小化框架开销的极简场景
项目结构示例
nest-demo/
├── package.json
├── tsconfig.json
├── src/
│ ├── main.ts
│ ├── app.module.ts
│ └── users/
│ ├── users.controller.ts
│ └── users.service.ts
└── (其余由 CLI 生成)
-
app.module.ts: 根模块
-
users/: 领域模块,控制器 + 服务
快速开始(推荐 CLI)
npx @nestjs/cli new nest-demo
cd nest-demo && npm run start:dev
代码示例
typescript
// app.module.ts
@Module({
controllers: [UsersController],
providers: [UsersService],
})
export class AppModule {}
// users.service.ts
@Injectable()
export class UsersService {
findAll() {
return [{ id: '1', name: 'John' }];
}
}
// users.controller.ts
@Controller('users')
export class UsersController {
constructor(private usersService: UsersService) {}
@Get()
findAll() {
return this.usersService.findAll();
}
}
Next.js
简介
Next.js 是 Vercel 开发的 React 全栈框架,专注于生产环境的最佳实践。它不仅是一个前端框架,还提供了完整的后端 API 支持。
实现原理
核心特性
- 文件系统路由 :
pages目录自动生成路由 - 服务端渲染(SSR) :
getServerSideProps在服务器端获取数据 - 静态生成(SSG) :
getStaticProps在构建时生成静态页面 - 增量静态再生(ISR):按需重新生成静态页面
- API 路由 :
pages/api目录创建 API 端点 - Image 优化:自动图片优化和懒加载
渲染模式
┌─────────────────────────────────────┐
│ Next.js 渲染模式 │
├─────────────────────────────────────┤
│ 1. SSR (Server-Side Rendering) │
│ - getServerSideProps │
│ - 每次请求都渲染 │
├─────────────────────────────────────┤
│ 2. SSG (Static Site Generation) │
│ - getStaticProps │
│ - 构建时生成静态页面 │
├─────────────────────────────────────┤
│ 3. ISR (Incremental Static Regeneration) │
│ - getStaticProps + revalidate │
│ - 按需重新生成静态页面 │
└─────────────────────────────────────┘
API 路由原理
Next.js 在内部使用 Node.js HTTP 模块,为 pages/api 中的每个文件创建一个 HTTP 端点。
性能表现
指标
- 吞吐量:优秀
- 延迟:SSR 较高,SSG/ISR 极低
- 首屏加载:SSG/ISR 极快
- SEO:完美支持
性能特点
-
优势:
- SSG 模式性能最优(CDN 可缓存)
- 自动代码分割和懒加载
- 图片优化减少带宽
- 内置性能监控
-
劣势:
- SSR 模式下服务器压力大
- 构建时间较长(大型项目)
基准测试
- SSG 静态页面:~100,000+ RPS(CDN 缓存)
- SSR 动态页面:~5,000-10,000 RPS(取决于数据源)
- API 路由:中等(基于 Node.js 性能)
适用场景
理想场景
- React 全栈应用:前端 + 后端 API
- SEO 要求高的项目:新闻网站、博客、电商
- JAMstack 架构:静态生成 + API 调用
- 需要快速部署:内置部署优化(Vercel)
- 混合渲染:部分页面静态,部分动态
- 国际化应用:内置 i18n 支持
不适用场景
- 纯后端 API(使用 Nest.js、Express 等)
- 不需要 React 的项目
- 完全动态的实时应用(考虑 Socket.io 等)
项目结构示例
next-demo/
├── package.json
├── pages/
│ ├── index.js
│ └── api/
│ └── hello.js
└── components/
└── Nav.js
-
pages/ : 文件即路由;
pages/api为后端 API -
components/: 可复用 UI 组件
快速开始
npx create-next-app@latest next-demo
cd next-demo && npm run dev
代码示例
javascript
// pages/index.js (SSG)
export default function Home({ posts }) {
return (
<div>
{posts.map(post => (
<article key={post.id}>{post.title}</article>
))}
</div>
);
}
export async function getStaticProps() {
const posts = await fetchPosts();
return { props: { posts } };
}
// pages/api/users.js (API Route)
export default function handler(req, res) {
res.status(200).json({ users: [] });
}
核心结构示例:Next.js
javascript
// pages/index.js(SSG)
export default function Home({ posts }) { return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>; }
export async function getStaticProps() { return { props: { posts: [] } }; }
// pages/posts/[id].js(SSR)
export default function Post({ post }) { return <h1>{post.title}</h1>; }
export async function getServerSideProps({ params }) { return { props: { post: { id: params.id, title: 'Post' } } }; }
// pages/api/hello.js(API Route)
export default function handler(req, res) { res.status(200).json({ ok: true }); }
渲染模式说明:
- SSG (Static Site Generation) :
pages/index.js- 构建时生成,性能最优 - SSR (Server-Side Rendering) :
pages/posts/[id].js- 每次请求都重新渲染 - CSR (Client-Side Rendering) :
pages/posts/create.js- 完全客户端渲染 - API Routes :
pages/api/*- 服务器端 API,运行在 Node.js 环境
Fastify
简介
Fastify 是 2017 年发布的极速 Node.js Web 框架,专门为高性能而设计。在保持简洁 API 的同时,提供强大的插件系统。
实现原理
核心特性
- 极速性能:基于异步/等待和高性能 HTTP 解析器
- JSON Schema 验证:内置 schema 验证,自动生成文档
- 插件系统:超轻量插件架构,支持异步插件注册
- TypeScript 支持:完整的类型定义
- 日志系统:高性能 Pino 日志库
性能优化机制
1. 对象池化(Object Pooling)
2. 提前生成路由匹配器(Route Matcher Pre-compilation)
3. 高速 JSON 序列化
4. HTTP/2 支持
5. 零开销抽象层
Schema 验证
javascript
const schema = {
schema: {
body: {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'integer' }
},
required: ['name']
}
}
};
fastify.post('/user', schema, async (request, reply) => {
return { success: true };
});
Fastify 在验证时编译 JSON Schema,后续请求直接使用编译后的验证器,性能极佳。
性能表现
指标
- 吞吐量:业界顶级(约是 Express 的 2-3 倍)
- 延迟:极低
- 内存占用:低
- 初始化速度:快
性能特点
-
优势:
- 吞吐量最高(基准测试领先)
- 内存占用低
- 验证性能优秀(编译后的 schema)
-
劣势:
- 生态相对较小(但快速增长)
- 不兼容 Express 中间件
基准测试
- 简单 JSON 响应:~40,000-60,000+ RPS(取决于硬件)
- 复杂请求处理:性能依然优秀
- 内存效率:内存占用显著低于其他框架
基准测试数据(参考)
框架对比(RPS - Requests Per Second):
Fastify: ~60,000
Koa: ~25,000
Express: ~15,000
Hapi: ~12,000
注意:实际性能取决于硬件和测试场景
适用场景
理想场景
- 高性能 API:需要极致吞吐量的场景
- 微服务:轻量级、低延迟
- 实时应用:WebSocket 服务器
- 边缘计算:Cloudflare Workers、Lambda
- JSON API:需要快速 JSON 处理
- 需要验证的应用:内置高性能 schema 验证
不适用场景
- 需要直接使用 Express 中间件
- 极小项目(但 Fastify 也很简洁)
- 团队不熟悉插件生态系统
项目结构示例
fastify-demo/
├── package.json
├── app.js
├── routes/
│ └── users.js
└── plugins/
└── db.js
-
app.js: 实例化 fastify、注册插件与路由
-
routes/users.js: 路由与 schema 校验
-
plugins/db.js: 数据库或服务封装为插件
快速开始
npm init -y
npm i fastify @fastify/helmet
node app.js
代码示例
javascript
const fastify = require('fastify')({ logger: true });
// Schema 定义
const userSchema = {
body: {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'integer' }
},
required: ['name']
}
};
// 路由
fastify.post('/user', { schema: userSchema }, async (request, reply) => {
return { success: true, user: request.body };
});
// 插件
fastify.register(require('@fastify/helmet'));
// 启动
fastify.listen(3000);
核心结构示例:Fastify
javascript
const fastify = require('fastify')({ logger: true });
// 1) 插件注册
// fastify.register(plugin)
// 2) 路由 + JSON Schema 验证
fastify.get('/users', async () => []);
fastify.post('/users', {
schema: { body: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] } }
}, async (request) => request.body);
// 3) 错误与 404 处理
fastify.setErrorHandler((err, req, reply) => reply.code(500).send({ error: err.message }));
fastify.setNotFoundHandler((req, reply) => reply.code(404).send({ error: 'Not Found' }));
框架对比总结
性能对比表
| 框架 | 吞吐量 (RPS) | 延迟 | 内存占用 | 学习曲线 | 生态规模 |
|---|---|---|---|---|---|
| Fastify | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| Koa | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| Express | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Nest.js | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| Next.js | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Hapi | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
架构对比
| 框架 | 架构特点 | 中间件模型 | 典型场景 |
|---|---|---|---|
| Express | 传统、简单 | 链式模型 | 传统 Web 应用、API |
| Koa | 现代、简洁 | 洋葱模型 | 异步应用、API |
| Nest.js | 企业级、模块化 | 模块化架构 | 大型团队、TypeScript |
| Next.js | 全栈、SSR/SSG | React 集成 | SEO 优化、全栈应用 |
| Hapi | 配置驱动、完整 | 插件模型 | 企业级、复杂业务 |
| Fastify | 极速、轻量 | 插件模型 | 高性能 API、微服务 |
核心技术差异
1. 中间件执行模型
- Express: 链式执行(Callbacks)
- Koa: 洋葱模型(Generator/Async)
- Fastify: 插件 + 钩子系统
- Hapi: 生命周期钩子
2. 路由系统
- Express: 手动定义路由表
- Koa: 需要外部路由库(koa-router)
- Fastify: 内置高效路由系统
- Nest.js: 装饰器定义(@Get, @Post)
- Next.js: 文件系统路由
- Hapi: 配置对象定义
3. 验证机制
- Express: 依赖中间件(express-validator, joi)
- Koa: 外部库
- Fastify: 内置 JSON Schema 验证(高性能)
- Hapi: 内置 Joi 验证
- Nest.js: class-validator(装饰器)
4. 类型支持
- Express: 需要额外类型定义(@types/express)
- Koa: 需要额外类型定义
- Fastify: 内置类型支持,优秀的 TypeScript 集成
- Hapi: 需要额外类型定义
- Nest.js: TypeScript 原生
- Next.js: TypeScript 原生
总结
- 性能之王:Fastify - 吞吐量最高,适合高性能场景
- 生态最广:Express.js - 最成熟,学习资源最丰富
- 现代异步:Koa.js - 洋葱模型,优雅的异步控制
- 企业级:Nest.js - 完整的架构支持,TypeScript 原生
- 全栈框架:Next.js - React 全栈,SSR/SSG 支持
- 企业完整方案:Hapi.js - 配置驱动,内置功能丰富
Fastify 项目最佳实践
如何组织代码结构
Fastify 推荐的模块化组织:
javascript
// 项目结构示例
project/
├── src/
│ ├── routes/
│ │ ├── users.js // ~150 行
│ │ ├── posts.js // ~150 行
│ │ └── comments.js // ~150 行
│ ├── plugins/
│ │ ├── auth.js // ~200 行
│ │ ├── database.js // ~200 行
│ │ └── validation.js // ~150 行
│ ├── services/
│ │ ├── userService.js // ~300 行
│ │ └── postService.js // ~300 行
│ ├── schemas/
│ │ ├── userSchema.js // ~50 行
│ │ └── postSchema.js // ~50 行
│ └── utils/
│ ├── logger.js // ~100 行
│ └── validator.js // ~150 行
└── app.js // ~100 行
代码拆分策略
1. 按功能模块拆分
javascript
// ❌ 不推荐:一个文件包含所有路由
// routes.js
fastify.get('/users', handler1);
fastify.get('/posts', handler2);
fastify.get('/comments', handler3);
// ... 50+ 路由
// ✅ 推荐:按功能拆分
// routes/users.js (~150 行)
fastify.register(async function (fastify) {
fastify.get('/users', getUserHandler);
fastify.get('/users/:id', getUserByIdHandler);
fastify.post('/users', createUserHandler);
// ... 5-10 个相关路由
});
2. 提取 Schema 定义
javascript
// ❌ 不推荐:schema 定义混在路由中
fastify.post('/users', {
schema: {
body: {
type: 'object',
properties: { /* 100+ 行定义 */ }
}
}
}, handler);
// ✅ 推荐:独立 schema 文件
// schemas/userSchema.js
export const createUserSchema = {
type: 'object',
properties: { /* ... */ }
};
// routes/users.js
import { createUserSchema } from '../schemas/userSchema.js';
fastify.post('/users', { schema: { body: createUserSchema } }, handler);
3. 拆分服务层
javascript
// ❌ 不推荐:业务逻辑写在路由中
fastify.get('/users/:id', async (request, reply) => {
// 50+ 行业务逻辑
const user = await db.query(...);
const posts = await db.query(...);
const comments = await db.query(...);
return { user, posts, comments };
});
// ✅ 推荐:提取到服务层
// services/userService.js
export async function getUserWithDetails(id) {
const [user, posts, comments] = await Promise.all([
db.getUser(id),
db.getPostsByUserId(id),
db.getCommentsByUserId(id)
]);
return { user, posts, comments };
}
// routes/users.js
import { getUserWithDetails } from '../services/userService.js';
fastify.get('/users/:id', async (request, reply) => {
return getUserWithDetails(request.params.id);
});
Fastify 插件组织的优势
Fastify 的插件系统天然支持代码拆分:
javascript
// ✅ 使用 Fastify 插件封装(推荐模式)
// users.plugin.js
const fp = require('fastify-plugin');
module.exports = fp(async function usersPlugin(fastify, opts) {
// 装饰服务
fastify.decorate('userService', {
list: async () => [{ id: 1, name: 'Alice' }],
});
// 作用域内钩子
fastify.addHook('onRequest', async (req) => { /* auth/trace */ });
// 路由(可配前缀)
fastify.get('/users', async (req, reply) => {
return await fastify.userService.list();
});
}, { name: 'users' });
// app.js
fastify.register(require('./plugins/users'));
插件系统的优势:
- ✅ 作用域隔离(避免全局污染)
- ✅ 按需加载(可以条件性注册)
- ✅ 自动管理封装形式
- ✅ 支持异步初始化