つらくないフロントエンドのディレクトリ構造を目指して2025
フロントエンドのディレクトリ構造について、過去にも取り上げたことがありますが、時間の経過とともに考え方が変化したため、改めて整理しました。今回紹介する構成はNext.jsを想定していますが、他のフレームワークにも応用可能な部分が多くあります。
ディレクトリ構造
src/
├ app/
│ ├ layout.tsx
│ └ page.tsx
├ actions/
├ components/
│ ├ base/
│ │ ├ atoms/
│ │ └ molecules/
│ └ case/
│ └ case-name/
│ ├ atoms/
│ └ molecules/
├ features/
│ └ feature-name/
│ ├ components/
│ │ ├ atoms/
│ │ └ molecules/
│ ├ schemas.ts
│ ├ converters.ts
│ ├ hooks.ts
│ ├ providers.ts
│ └ contexts.ts
├ libs/
├ utils/
│ └ result.ts
└ stores/
└ store-name/
├ types.ts
├ atoms.ts
├ operations.ts
└ selectors.ts
ディレクトリの概要
app/
Next.jsのlayout.tsx
は主にメタタグの設定に使用し、レイアウトの管理は個別のレイアウトコンポーネントで行います。レイアウトをlayout.tsx
で管理しない理由は以下の通りです。
-
layout.tsx
ではpropsを渡せない - 配下の
page.tsx
に一律適用され、柔軟なレイアウトの切り替えが困難
レイアウトの切り替えにはRoute Groupsを活用することもできますが、あとから変更すると差分が大きかったり配下のページに一律に適用されるのは結局変わらなかったりするのでレイアウトコンポーネントを別途作成する方針を採用します。
レイアウトコンポーネントをsiteドメインに配置するか、またはlayouts/
ディレクトリを用意するかはまだ決めあぐねています。
actions/
Next.jsのActionsを格納するディレクトリです。以前はapp/
配下に各々配置していましたが、依存関係が複雑になりやすいため、src/
直下に統一しました。
components/
コンポーネントを管理するディレクトリです。コンポーネントの構成はBCD Designに基づいています。ただし、ドメインに関連するコンポーネントはfeatures/
に配置します。
また、app/
配下には_components/
ディレクトリを設けません。コンポーネントを並べて見た際に粒度がそろっていると感じられることが重要なので、コンポーネントはcomponents/
とfeatures/
でのみ管理します。
features/
ドメインごとの機能をまとめるディレクトリです。
converters.ts
いわゆる抽象化レイヤーです。
例えばバックエンドのレスポンスをfeatures/
内で定義したスキーマに変換する変換器を定義します。OpenAPIなどから生成されたバックエンドのスキーマをそのまま使用せず、フロントエンドはfeatures/
で定義したスキーマにのみ依存する設計を採用します。これにより、フロントエンドがバックエンドに直接依存することを防ぎます。
libs/
ライブラリのラッパーなど、特定のライブラリに関するカスタムユーティリティを格納するディレクトリです。
utils/
汎用的なユーティリティ関数などを管理するディレクトリです。特定のドメインに依存しないもののみをutils/
に配置し、関心があるものはfeatures/
に格納します。
result.ts
エラーハンドリングにResult型を使用するためのユーティリティです。エラーをthrow
するのではなく、すべてResult型を返す方針とします。
type Ok<T> = {
ok: true;
data: T;
};
type Err<E extends Error> = {
ok: false;
error: E;
};
export type Result<T, E extends Error> = Ok<T> | Err<E>;
stores/
グローバルな状態管理を行うディレクトリです。グローバルな状態管理は極力控えますが、必要な場合はstores/
に配置します。stores/
の詳細なディレクトリ構造は以下を参照してください。
作らないディレクトリについて
features/
ディレクトリを見ていただけると分かる通り、hooks/
やproviders/
といったディレクトリは作りません。package by feature
の理念については以下の記事を参照してください。
まとめ
本構成はフロントエンド開発において特につらくなりやすいコンポーネントの粒度と依存関係の不整合を解決することを図っています。
ポイントはBCD Designと抽象化レイヤーです。これらを活用することでコンポーネントの粒度の統一と依存関係の整理を実現し、スケールしやすいフロントエンドの設計を意識しています。
Discussion