为什么 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。