フロントエンドチームは、開発環境のみで動作する型安全なAPIモッキングレイヤーを導入しました。AxiosのインターセプターとViteのツリーシェイキングを活用することで、本番用のバンドルには一切影響を与えません。エンジニアはバックエンドのエンドポイントが完成するのを待つ間、いつものパターンでデータをフェッチでき、環境フラグを一つ切り替えるだけで実際のAPIに接続できます。

なぜチームはより良いモック手法を必要としたのか

バックエンドのルートが未完成のとき、フロントエンド開発者は行き詰まってしまいます。コンポーネント内にレスポンスをハードコードしたり、UIの至る所に if (process.env.NODE_ENV === 'development') ブロックを散りばめたりといった場当たり的な対応は、開発を継続させることはできますが、技術的負債を残します。それらのモックオブジェクトはコンポーネントのロジックの一部となり、本番環境に偽のデータを送り込んでしまうリスクを高め、コードの可読性やテストのしやすさを低下させます。

チームは、すべてのモックをコンポーネントツリーから切り離し、フロントエンドとバックエンド間のコントラクト(規約)を強制し、本番ビルドに余計なものが含まれないことを保証したいと考えました。

チームが実践している3つのステップ

  1. コントラクト会議 – フロントエンドとバックエンドのエンジニアが話し合い、各リクエスト、URL、メソッド、および期待されるペイロードをリストアップします。
  2. 型定義されたコントラクト – リストをTypeScriptのインターフェースに変換し、リクエストとレスポンスの形状に関する「信頼できる唯一の情報源(single source of truth)」とします。
  3. インターセプターの組み込み – Axiosのインターセプターがすべての送信リクエストを検証します。URLが登録済みのモックと一致する場合、インターセプターはモックデータを返し、一致しない場合はリクエストがライブサーバーへと進みます。

インターセプターがモックロジックの唯一の存在場所であるため、コンポーネントのコードを変更する必要はありません。開発者は、条件分岐ロジックを追加することなく、useQuery などの通常のデータフェッチ用フックをそのまま使い続けることができます。

本番環境の肥大化をどのように防いでいるか

チームは、本番ビルド時に(Viteで使用されているバンドラーである)Rollupがモックコードを完全に削除できるように、3つのセーフガードを設けました。

  • 本番ビルドでは import.meta.env.DEVfalse に解決されるため、ツリーシェイキングによってインターセプターモジュール全体が消失します。
  • ユニットテストの実行時には MODE 変数が test 以外の値に設定されるため、テスト専用のコードが分離されます。
  • カスタムフラグ VITE_ENABLE_MSW はデフォルトで false に設定されており、モックを有効にするには明示的にオンにする必要があります。

これら3つの条件がすべて false の場合、モックレジストリが最終的なバンドルに含まれることはありません。

モックファイルの構成

リポジトリは機能中心のレイアウトに従っています。

  • interfaces/ – コントラクト会議から生成されたTypeScriptの定義を保持します。
  • scenarios.ts – 各エンドポイントにおける成功レスポンスやエラーケースの具体的な例を含みます。
  • devHandlers.ts – URLをシナリオデータにマッピングし、インターセプターをAxiosに接続する中央レジストリとして機能します。

小さなスキャフォールディング(雛形生成)スクリプトを使用して、これらのファイルを自動生成できます。URLと対応するインターフェースを渡すだけで、スタブファイルを作成し、モックを登録します。このスクリプトは本番コードのパスの外にあるため、バンドルサイズに影響を与えません。

チームが得たメリット

  • コンポーネント内にモックが存在しない – すべての偽データは専用のレイヤーに存在するため、UIコードをクリーンに保てます。
  • エンドツーエンドの型安全性 – モックデータは実際のレスポンスで使用されるものと同じTypeScriptインターフェースに従うため、不一致はコンパイル時に検出されます。
  • 本番環境への影響なし – ツリーシェイキングによってインターセプターとモックデータが完全に削除されるため、バンドルサイズは変わりません。
  • 開発とテストでシナリオを共有 – 同じモック定義がローカル開発と自動テストの両方に使用されるため、重複が削減されます。

トレードオフと限界

このアプローチは本物のバックエンドに取って代わるものではありません。モックのコントラクトが実際のAPIと乖離している場合、開発者がその不一致に気づくのは、環境フラグを切り替えた後になります。

今後の展望

  • ツール統合
  • より広範な採用
  • パフォーマンスモニタリング

結論は明確です。モックロジックを型定義され、環境によって制御されるレイヤーに移動することで、フロントエンドチームはコンポーネントを純粋な状態に保ち、型安全性を維持し、隠れたモックペイロードなしで本番ビルドをリリースできます。共有のコントラクトを維持することは、よりスムーズな開発ワークフローとクリーンなコードベースを実現するための代償といえます。