后端工程Technical Deep Dive

Express vs Fastify:企业级 Web 框架对比

发布时间2026/03/29
分类后端工程
预计阅读10 分钟
作者吴长龙
*

Express vs Fastify:企业级 Web 框架对比

01.内容

# Express vs Fastify:企业级 Web 框架对比

选择合适的 Web 框架是后端开发的第一步。Express 和 Fastify 是 Node.js 生态中最流行的两个框架,本文从性能、生态、易用性等多个维度进行深入对比,帮助你做出明智的选择。

02.一、背景与定位

Express:老牌霸主

Express 自 2009 年发布以来,一直是 Node.js Web 框架的事实标准。它的设计理念是"最小化 + 可扩展",通过中间件机制让开发者自由组织代码。

特点

  • 简单灵活的路由
  • 丰富的中间件生态
  • 几乎所有 Node.js 教程都使用 Express

Fastify:性能优先

Fastify 于 2016 年发布,定位是"高性能、低开销"的 Web 框架。它在设计时充分考虑了 TypeScript 支持和 Type safety。

特点

  • 基于 schema 的验证(JSON Schema)
  • 极致的性能优化
  • 内置日志系统
  • 插件生态系统

03.二、性能对比

基准测试数据

根据多个独立测试机构的基准测试:

指标ExpressFastify差异
QPS (Hello World)~15,000~70,000Fastify 快 4-5x
内存占用较高较低Fastify 省 30-50%
首字节时间 (TTFB)较高较低Fastify 更低
冷启动时间较快较快相差不大

实际业务场景测试

javascript snippetjavascript
// 测试代码:模拟真实业务场景
const express = require('express');
const fastify = require('fastify');

// Express
const expressApp = express();
expressApp.get('/api/users/:id', (req, res) => {
  const { id } = req.params;
  // 模拟数据库查询
  const user = { id, name: 'User ' + id, role: 'admin' };
  res.json(user);
});

// Fastify
const fastifyApp = fastify({ logger: false });
fastifyApp.get('/api/users/:id', async (req, reply) => {
  const { id } = req.params;
  const user = { id, name: 'User ' + id, role: 'admin' };
  return user;
});

// 两者在处理真实业务逻辑时性能差距会缩小
// 但 Fastify 仍然有 2-3x 的优势

性能差异的根源

  • 路由处理:Fastify 使用自定义的路由树,比 Express 的正则匹配更快
  • 中间件机制:Express 的 use() 会遍历所有中间件,Fastify 采用更高效的 Hook 机制
  • Schema 验证:Fastify 在启动时编译 schema,运行时几乎零开销
  • 对象复用:Fastify 复用请求/响应对象,减少 GC 压力

04.三、代码对比

3.1 基础路由

javascript snippetjavascript
// Express
const express = require('express');
const app = express();

app.get('/api/users', (req, res) => {
  res.json({ users: [] });
});

app.post('/api/users', (req, res) => {
  const user = req.body;
  // 处理创建
  res.status(201).json(user);
});

// Fastify
const fastify = require('fastify');
const app = fastify({ logger: true });

app.get('/api/users', async (request, reply) => {
  return { users: [] };
});

app.post('/api/users', async (request, reply) => {
  const user = request.body;
  return reply.status(201).send(user);
});

3.2 中间件 vs Hooks

javascript snippetjavascript
// Express 中间件
app.use((req, res, next) => {
  console.log('请求开始:', req.method, req.url);
  next();
});

app.use((req, res, next) => {
  // 认证逻辑
  if (req.headers.authorization) {
    next();
  } else {
    res.status(401).json({ error: '未授权' });
  }
});

// Fastify Hooks
app.addHook('onRequest', async (request, reply) => {
  console.log('请求开始:', request.method, request.url);
});

app.addHook('preHandler', async (request, reply) => {
  if (!request.headers.authorization) {
    reply.status(401).send({ error: '未授权' });
  }
});

3.3 参数验证

javascript snippetjavascript
// Express:手动验证(繁琐)
app.post('/api/users', (req, res, next) => {
  const { name, email } = req.body;
  
  if (!name || name.length < 2) {
    return res.status(400).json({ error: '名字至少2个字符' });
  }
  
  if (!email || !email.includes('@')) {
    return res.status(400).json({ error: '无效的邮箱' });
  }
  
  next();
});

// Fastify:Schema 声明(声明式)
const createUserSchema = {
  body: {
    type: 'object',
    required: ['name', 'email'],
    properties: {
      name: { type: 'string', minLength: 2 },
      email: { type: 'string', format: 'email' }
    }
  },
  response: {
    201: {
      type: 'object',
      properties: {
        id: { type: 'string' },
        name: { type: 'string' },
        email: { type: 'string' }
      }
    }
  }
};

app.post('/api/users', { schema: createUserSchema }, async (request, reply) => {
  const { name, email } = request.body;
  // 创建用户
  return reply.status(201).send({ id: '1', name, email });
});

05.四、生态系统

4.1 中间件/插件

javascript snippetjavascript
// Express 生态
const helmet = require('helmet');           // 安全头
const cors = require('cors');               // 跨域
const morgan = require('morgan');           // 日志
const expressRateLimit = require('express-rate-limit'); // 限流
const bodyParser = require('body-parser');  // 解析

app.use(helmet());
app.use(cors());
app.use(morgan('dev'));
app.use(expressRateLimit({ windowMs: 15*60*1000, max: 100 }));
app.use(bodyParser.json());

// Fastify 生态(命名约定 @fastify/xxx)
await app.register(require('@fastify/helmet'));
await app.register(require('@fastify/cors'));
await app.register(require('@fastify/rate-limit'));
// Fastify 内置 body 解析,无需额外中间件

4.2 TypeScript 支持

typescript snippettypescript
// Fastify 原生 TypeScript 支持
import Fastify, { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';

interface UserParams {
  id: string;
}

interface CreateUserBody {
  name: string;
  email: string;
}

const app: FastifyInstance = Fastify();

app.get<{ Params: UserParams }>('/api/users/:id', async (
  request: FastifyRequest<{ Params: UserParams }>,
  reply: FastifyReply
) => {
  const { id } = request.params;
  return { id, name: 'John' };
});

app.post<{ Body: CreateUserBody }>('/api/users', async (
  request: FastifyRequest<{ Body: CreateUserBody }>,
  reply: FastifyReply
) => {
  const { name, email } = request.body;
  return reply.status(201).send({ id: '1', name, email });
});

// Express 需要额外安装 @types/express
// 并且类型推断不如 Fastify 精确

4.3 路由注册方式

javascript snippetjavascript
// Express 路由文件
// users.js
module.exports = (app) => {
  app.get('/users', listUsers);
  app.get('/users/:id', getUser);
  app.post('/users', createUser);
};

// 路由拆分
const usersRouter = require('./routes/users');
const ordersRouter = require('./routes/orders');
app.use('/api/users', usersRouter);
app.use('/api/orders', ordersRouter);

// Fastify 路由拆分(推荐)
// users.js
async function userRoutes(fastify, options) {
  fastify.get('/', listUsers);
  fastify.get('/:id', getUser);
  fastify.post('/', createUser);
}

// 插件化注册
await app.register(userRoutes, { prefix: '/api/users' });
await app.register(orderRoutes, { prefix: '/api/orders' });

06.五、生产环境选择

5.1 何时选择 Express

场景原因
快速原型开发文档丰富,学习曲线低
维护现有项目团队熟悉,生态成熟
简单 REST API功能足够,不需要极致性能
需要大量第三方中间件Express 中间件生态更丰富

5.2 何时选择 Fastify

场景原因
高性能 API性能优势明显
TypeScript 项目原生 TS 支持
需要严格的输入验证内置 JSON Schema
微服务架构轻量、快速启动
需要内置日志/监控丰富的平台特性

5.3 企业级建议

javascript snippetjavascript
// 实际建议:根据团队和技术栈选择

// 小团队、快速迭代 -> Express
// 优势:学习成本低,招聘容易,文档丰富

// 大团队、性能敏感 -> Fastify
// 优势:类型安全,性能优异,内置功能多

// 或者:混合使用
// - 内部工具/管理后台:Express(开发快)
// - 对外 API 服务:Fastify(性能好)
// - 新项目:直接 Fastify(面向未来)

07.六、迁移指南

从 Express 迁移到 Fastify

javascript snippetjavascript
// Step 1: 安装
// npm i fastify

// Step 2: 基本结构迁移
const express = require('express');
const app = express();

// 旧代码
app.use(express.json());
app.get('/api/health', (req, res) => res.json({ status: 'ok' }));

// 新代码
const fastify = require('fastify');
const app = fastify({ logger: true });

// Fastify 自动解析 JSON,无需中间件
app.get('/api/health', async () => ({ status: 'ok' }));

// Step 3: 错误处理
// Express
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: '服务器错误' });
});

// Fastify
app.setErrorHandler((error, request, reply) => {
  request.log.error(error);
  reply.status(500).send({ error: '服务器错误' });
});

// Step 4: 启动服务
// Express: app.listen(3000)
// Fastify: app.listen({ port: 3000 })

08.总结

维度ExpressFastify
性能中等极高
学习曲线中等
TypeScript需额外配置原生支持
验证机制手动/自定义JSON Schema
生态成熟度中等(快速增长)
更新维护较少活跃

最终建议:如果是新项目且团队有一定 TypeScript 经验,直接选择 Fastify。如果是维护现有 Express 项目,或者需要快速开发小工具,Express 仍然是可靠的选择。两者都是经过大量生产验证的框架,选择哪个都不会有太大问题。