mcpField
F
fastify

fastify

github.com/bobmatnyc開発78575 回インストール15 週間前に更新
リポジトリ

fastify について

TypeScript 開発者向けの Fastify による Node.js バックエンド構築ガイドです。スキーマ検証、カプセル化されたプラグイン、エラー処理、セキュリティ、正常終了、インメモリでのルートテストを扱います。

主な機能

  1. 01スキーマによるリクエストとレスポンスの検証
  2. 02カプセル化されたプラグインでルートを整理
  3. 03エラー処理の一元化
  4. 04セキュリティプラグインとペイロード制限
  5. 05プロセスシグナルに応じた正常終了
  6. 06インメモリインジェクションでルートをテスト

活用シーン

  1. 01型付き Node.js HTTP API の構築
  2. 02ルートと依存関係の分離
  3. 03ハンドラーから一貫したエラーを返す
  4. 04ポートを開かずにエンドポイントをテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill fastify

インストール後、Claude Code で/fastifyを入力して読み込まれたか確認します。

同梱ファイルmetadata.json

詳細

Fastify(TypeScript) - 本番環境向けバックエンドフレームワーク

概要

Fastify は、JSON スキーマによるバリデーション、カプセル化されたプラグイン、優れた開発者体験を中心に構築された、高性能な Node.js ウェブフレームワークです。TypeScript では、型プロバイダー(Zod または TypeBox)と Fastify を組み合わせることで、実行時のバリデーションと静的型を一致させられます。

クイックスタート

最小限のサーバー

✅ 正しい例:型付きレスポンスを返す基本的なサーバー

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

スキーマバリデーションと型プロバイダー

Fastify は JSON スキーマを使ってリクエストとレスポンスを検証します。型の重複を避けるには、型プロバイダーを使用します。

Zod プロバイダー(フルスタック TypeScript におすすめ)

✅ 正しい例:Zod スキーマでバリデーションと型を定義する

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 スキーマ

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 サーバーと下流のクライアント(DB、キュー)を終了します。

✅ 正しい例:シグナル受信時に終了する

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)

ポートをバインドせずに、メモリ上でルートをテストします。

✅ 正しい例:リクエストを 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 の比較
  • スキーマベースのバリデーション、予測可能なプラグイン、高いスループットを重視する場合は、Fastify をおすすめします。
  • 最小限のミドルウェアと、幅広く親しまれているエコシステムを重視する場合は、Express をおすすめします。
Zod と TypeBox の比較
  • フォーム、tRPC、共有型など、すでに Zod を標準としているアプリケーションのコードベースには、Zod をおすすめします。
  • OpenAPI の生成や、パフォーマンスが重要なバリデーションには、TypeBox をおすすめします。

アンチパターン

  • リクエストのバリデーションを省略する。境界でスキーマを使って検証します。
  • すべてを main.ts に登録する。ルートと依存関係をプラグインに分離します。
  • 生のエラーオブジェクトを返す。安定した形式のエラーを返し、詳細はログに記録します。

リソース

コメント