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() 提供静态文件服务
中间件机制
// Express 中间件执行流程
app.use((req, res, next) => {
  // 执行逻辑
  next(); // 调用下一个中间件
});

Express 使用同步式中间件链,通过回调函数 next() 来控制请求流程。中间件按照注册顺序执行。

路由系统
  • 使用路由表(Route Table)存储路由规则
  • 通过正则表达式匹配 URL 路径
  • 支持参数路由和通配符

性能表现

指标
  • 吞吐量:中等
  • 延迟:较中等
  • 内存占用:中等
  • 初始化速度:快
性能特点
  • 优势:成熟稳定,生态系统完善
  • 劣势:性能不是最优,相比 Fastify 和 Koa 略慢
基准测试(RPS - Requests Per Second)
  • 简单 JSON 响应:~15,000 RPS
  • 数据库查询:取决于数据库性能

适用场景

理想场景
  1. 传统 Web 应用:企业级应用、后台管理系统
  2. RESTful API:中等规模的 API 服务
  3. 快速原型开发:需要快速搭建项目
  4. 学习和教学:最广泛的教程资源
  5. 中小型项目:不需要极高性能的场景
不适用场景
  • 极高并发需求(每秒数十万请求)
  • 需要极致性能优化的场景

项目结构示例

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

代码示例

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

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 机制
洋葱模型
// 请求流程: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

适用场景

理想场景
  1. 现代异步应用:大量使用 async/await 的项目
  2. API 网关:需要复杂中间件处理逻辑
  3. 微服务架构:轻量级、高性能需求
  4. 需要精细控制的场景:使用洋葱模型处理请求/响应
  5. 高性能 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

代码示例

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

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(中间件)
依赖注入系统
// 服务定义
@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 性能
  • 复杂应用:优于传统架构(得益于模块化和依赖注入)

适用场景

理想场景
  1. 大型企业应用:需要清晰的架构和可维护性
  2. TypeScript 项目:完全基于 TypeScript
  3. 团队协作:多人开发,需要标准化架构
  4. 微服务架构:内置微服务支持
  5. 需要依赖注入:复杂的业务逻辑和依赖关系
  6. 从 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

代码示例

// 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 性能)

适用场景

理想场景
  1. React 全栈应用:前端 + 后端 API
  2. SEO 要求高的项目:新闻网站、博客、电商
  3. JAMstack 架构:静态生成 + API 调用
  4. 需要快速部署:内置部署优化(Vercel)
  5. 混合渲染:部分页面静态,部分动态
  6. 国际化应用:内置 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

代码示例

// 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

// 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 }); }

渲染模式说明

  1. SSG (Static Site Generation)pages/index.js - 构建时生成,性能最优
  2. SSR (Server-Side Rendering)pages/posts/[id].js - 每次请求都重新渲染
  3. CSR (Client-Side Rendering)pages/posts/create.js - 完全客户端渲染
  4. API Routespages/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 验证
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

注意:实际性能取决于硬件和测试场景

适用场景

理想场景
  1. 高性能 API:需要极致吞吐量的场景
  2. 微服务:轻量级、低延迟
  3. 实时应用:WebSocket 服务器
  4. 边缘计算:Cloudflare Workers、Lambda
  5. JSON API:需要快速 JSON 处理
  6. 需要验证的应用:内置高性能 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

代码示例

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

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 原生

总结

  1. 性能之王:Fastify - 吞吐量最高,适合高性能场景
  2. 生态最广:Express.js - 最成熟,学习资源最丰富
  3. 现代异步:Koa.js - 洋葱模型,优雅的异步控制
  4. 企业级:Nest.js - 完整的架构支持,TypeScript 原生
  5. 全栈框架:Next.js - React 全栈,SSR/SSG 支持
  6. 企业完整方案:Hapi.js - 配置驱动,内置功能丰富

Fastify 项目最佳实践

如何组织代码结构

Fastify 推荐的模块化组织

// 项目结构示例
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. 按功能模块拆分

// ❌ 不推荐:一个文件包含所有路由
// 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 定义

// ❌ 不推荐: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. 拆分服务层

// ❌ 不推荐:业务逻辑写在路由中
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 的插件系统天然支持代码拆分:

// ✅ 使用 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'));

插件系统的优势

  • ✅ 作用域隔离(避免全局污染)
  • ✅ 按需加载(可以条件性注册)
  • ✅ 自动管理封装形式
  • ✅ 支持异步初始化
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐