关于 fastify
面向 TypeScript 开发者的 Fastify Node.js 后端构建指南,重点介绍模式验证、封装式插件、错误处理、安全措施、优雅关闭和内存路由测试。
主要功能
- 01用模式验证请求和响应
- 02通过封装式插件组织路由
- 03集中处理错误
- 04应用安全插件并限制载荷
- 05响应进程信号并优雅关闭
- 06通过内存注入测试路由
适用场景
- 01构建类型化的 Node.js HTTP API
- 02分离路由与依赖逻辑
- 03让处理器返回一致的错误
- 04无需开放端口即可测试端点
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ bobmatnyc/ claude-mpm-skills --skill fastify安装后在 Claude Code 中输入/fastify确认已加载。
附带文件metadata.json
详细介绍
Fastify(TypeScript)- 生产级后端框架
概述
Fastify 是一个高性能 Node.js Web 框架,基于 JSON Schema 验证、封装式插件和出色的开发体验构建。在 TypeScript 中,将 Fastify 与类型提供程序(Zod 或 TypeBox)搭配使用,可确保运行时验证与静态类型保持一致。
快速开始
最简服务器
✅ 正确:带类型响应的基本服务器
import Fastify from "fastify";
const app = Fastify({ logger: true });
app.get("/health", async () => ({ status: "ok" as const }));
await app.listen({ host: "0.0.0.0", port: 3000 });
❌ 错误:启动服务器时未等待 listen
app.listen({ port: 3000 });
console.log("started"); // races startup and hides bind failures
Schema 验证 + 类型提供程序
Fastify 通过 JSON Schema 验证请求和响应。使用类型提供程序可避免重复定义类型。
Zod 提供程序(推荐用于全栈 TypeScript)
✅ 正确:Zod Schema 驱动验证和类型
import Fastify from "fastify";
import { z } from "zod";
import { ZodTypeProvider } from "fastify-type-provider-zod";
const app = Fastify({ logger: true }).withTypeProvider<ZodTypeProvider>();
const Query = z.object({ q: z.string().min(1) });
app.get(
"/search",
{ schema: { querystring: Query } },
async (req) => {
return { q: req.query.q };
},
);
await app.listen({ port: 3000 });
TypeBox 提供程序(推荐用于 OpenAPI + 性能)
✅ 正确:TypeBox Schema
import Fastify from "fastify";
import { Type } from "@sinclair/typebox";
import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox";
const app = Fastify({ logger: true }).withTypeProvider<TypeBoxTypeProvider>();
const Params = Type.Object({ id: Type.String({ minLength: 1 }) });
const Reply = Type.Object({ id: Type.String() });
app.get(
"/users/:id",
{ schema: { params: Params, response: { 200: Reply } } },
async (req) => ({ id: req.params.id }),
);
await app.listen({ port: 3000 });
插件架构(封装)
使用插件隔离各项职责,便于测试(身份验证、数据库、路由)。
✅ 正确:路由插件
import type { FastifyPluginAsync } from "fastify";
export const usersRoutes: FastifyPluginAsync = async (app) => {
app.get("/", async () => [{ id: "1" }]);
app.get("/:id", async (req) => ({ id: (req.params as any).id }));
};
✅ 正确:注册时添加前缀
app.register(usersRoutes, { prefix: "/api/v1/users" });
错误处理
集中处理意外故障,并返回稳定的错误结构。
✅ 正确:setErrorHandler
app.setErrorHandler((err, req, reply) => {
req.log.error({ err }, "request failed");
reply.status(500).send({ error: "internal" as const });
});
安全加固(基线)
添加标准安全插件并限制负载大小。
✅ 正确:Helmet + CORS + 速率限制
import helmet from "@fastify/helmet";
import cors from "@fastify/cors";
import rateLimit from "@fastify/rate-limit";
await app.register(helmet);
await app.register(cors, { origin: false });
await app.register(rateLimit, { max: 100, timeWindow: "1 minute" });
优雅关闭
在 SIGINT/SIGTERM 时关闭 HTTP 服务器及下游客户端(数据库、队列)。
✅ 正确:在信号触发时关闭
const close = async (signal: string) => {
app.log.info({ signal }, "shutting down");
await app.close();
process.exit(0);
};
process.on("SIGINT", () => void close("SIGINT"));
process.on("SIGTERM", () => void close("SIGTERM"));
测试(Fastify inject)
在内存中测试路由,无需绑定端口。
✅ 正确:注入请求
import Fastify from "fastify";
import { describe, it, expect } from "vitest";
describe("health", () => {
it("returns ok", async () => {
const app = Fastify();
app.get("/health", async () => ({ status: "ok" as const }));
const res = await app.inject({ method: "GET", url: "/health" });
expect(res.statusCode).toBe(200);
expect(res.json()).toEqual({ status: "ok" });
});
});
决策树
Fastify 与 Express
- 如果需要基于 Schema 的验证、可预测的插件机制和高吞吐量,优先选择 Fastify。
- 如果需要精简的中间件和对生态系统的高度熟悉度,优先选择 Express。
Zod 与 TypeBox
- 如果应用代码库已统一使用 Zod(表单、tRPC、共享类型),优先选择 Zod。
- 如果需要生成 OpenAPI 文档和进行性能关键型验证,优先选择 TypeBox。
反模式
- 跳过请求验证;应在边界处使用 Schema 进行验证。
- 将所有内容都注册在
main.ts中;应将路由和依赖隔离到插件中。 - 返回原始错误对象;应返回稳定的错误结构,并记录详细信息。
资源
- Fastify:https://www.fastify.io/
- fastify-type-provider-zod:https://github.com/turkerdev/fastify-type-provider-zod
- @fastify/type-provider-typebox:https://github.com/fastify/fastify-type-provider-typebox
评论
支持 Markdown