为什么 Fastify
号称 Node 上最快的 HTTP 框架之一——基准跑分通常是 Express 的 2-3 倍。
特点:
- 性能优秀(路由树 + 编译 schema)
- TypeScript 一等公民
- 内置 JSON Schema 校验
- 插件系统强(每个插件独立作用域)
- 生态丰富
npm install fastify
最小服务
import Fastify from 'fastify';
const app = Fastify({ logger: true });
app.get('/', async (req, reply) => {
return { hello: 'world' };
});
await app.listen({ port: 3000, host: '0.0.0.0' });
路由
app.get('/users', async (req, reply) => ({ list: [...] }));
app.get('/users/:id', async (req, reply) => req.params.id);
app.post('/users', async (req, reply) => req.body);
app.put('/users/:id', async () => {});
app.delete('/users/:id', async () => {});
// 路由组 = prefix
await app.register((scope, opts, done) => {
scope.get('/', async () => ({ list: 'users' }));
scope.get('/:id', async (req) => req.params.id);
done();
}, { prefix: '/users' });
Schema 校验(杀手锏)
app.post('/users', {
schema: {
body: {
type: 'object',
required: ['name', 'email'],
properties: {
name: { type: 'string', minLength: 1 },
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 0 },
},
},
response: {
201: {
type: 'object',
properties: {
id: { type: 'string' },
name: { type: 'string' },
},
},
},
},
}, async (req, reply) => {
// req.body 已经过校验
const user = await createUser(req.body);
reply.code(201);
return user;
});
好处:
- 自动校验输入——不合 schema 直接 400
- 响应过滤——多余字段自动剔除
- 更快(生成的代码 + JSON 序列化是预编译的)
- 自动生成 OpenAPI 文档(配
@fastify/swagger)
响应
// 推荐:直接 return
async (req, reply) => {
return { ok: true };
}
// 或显式
async (req, reply) => {
reply.code(201);
reply.header('X-Custom', 'value');
reply.send({ ok: true });
}
// 重定向
reply.redirect('/new-path');
reply.redirect(301, '/permanent');
// 流式
reply.type('application/octet-stream');
reply.send(createReadStream('big.zip'));
插件系统
// my-plugin.js
import fp from 'fastify-plugin';
async function myPlugin(fastify, options) {
fastify.decorate('utility', () => 'hello');
fastify.addHook('onRequest', async (req) => {
req.startTime = Date.now();
});
}
export default fp(myPlugin);
// app.js
await app.register(import('./my-plugin.js'));
console.log(app.utility()); // 'hello'
fp() 包装让插件装饰主实例而不是隔离作用域。
钩子(hooks)
app.addHook('onRequest', async (req, reply) => {
// 请求最开始
});
app.addHook('preHandler', async (req, reply) => {
// 路由 handler 之前(鉴权放这)
});
app.addHook('onResponse', async (req, reply) => {
// 响应已发送
});
app.addHook('onError', async (req, reply, err) => {
// 出错时
});
错误处理
app.setErrorHandler((err, req, reply) => {
if (err.validation) {
return reply.code(400).send({ error: 'Validation failed', details: err.validation });
}
reply.code(err.statusCode || 500).send({ error: err.message });
});
常用插件
npm install @fastify/cors @fastify/helmet @fastify/jwt @fastify/swagger @fastify/static
await app.register(import('@fastify/cors'), { origin: '*' });
await app.register(import('@fastify/helmet'));
await app.register(import('@fastify/jwt'), { secret: 'mysecret' });
Fastify vs Express
| 维度 | Fastify | Express |
|---|---|---|
| 性能 | ★★★★★ | ★★★ |
| 生态 | 大 | 最大 |
| 学习曲线 | 中 | 低 |
| TypeScript | 一等公民 | OK 但要装 @types |
| Schema 校验 | 内置 | 第三方(如 zod) |
| 插件作用域 | 强 | 弱 |
| 文档 | 优秀 | 优秀 |
| 适合 | 新项目 / 高性能要求 | 学 Node / 老项目 / 团队熟悉 |
何时选 Fastify
- 性能敏感(高 QPS)
- TypeScript 项目
- 想自动文档化(swagger)
- 喜欢"约定 + schema"的开发体验
何时选 Express
- 团队都熟 Express
- 老项目
- 找 stackoverflow 答案最多
- 生态深度(中间件量级最大)
坑
- Fastify 的
req.body默认会被 schema 校验——没写 schema 等于裸接收 - Fastify 5+ 用 ESM——CJS 项目可能要 dynamic import
- 插件注册是异步的——一定要
await app.register(...) - 日志默认很啰嗦——生产配
logger: { level: 'info' }
下一篇:WebSocket。