🔥

React プロジェクト構成について考えてみた

に公開1

最近フロントエンドの技術を勉強していて、プロジェクトのフォルダ構成について自分なりに整理してみました。
まだ実務経験は浅く、一人で試行錯誤しながら進めているので「本当にこれでいいのかな?」という不安もあります。もし間違った考え方や実務ではあまりやらないやり方があれば、ぜひコメントで教えていただけると嬉しいです 🙏

React プロジェクト構成

project-root/
├── public/                    # 静的アセット (アイコン、画像、フォント)
├── src/
│   ├── pages/                 # ルーティングに対応するページ (薄いレイヤー、ほぼ container 呼び出しのみ)
│   │   ├── Home.tsx           # -> <HomeContainer />
│   │   ├── Dashboard.tsx      # -> <DashboardContainer />
│   │   └── Profile.tsx        # -> <ProfileContainer />
│   │
│   ├── containers/            # コンテナ層 (UI + hooks + 業務ロジックの組み合わせ)
│   │   ├── auth/
│   │   │   └── LoginFormContainer.tsx
│   │   ├── dashboard/
│   │   │   └── ArticleListContainer.tsx
│   │   └── chat/
│   │       └── ProfileContainer.tsx
│   │
│   ├── components/            # プレゼンテーション専用 UI コンポーネント
│   │   ├── ui/                # 基盤 UI (Button, Input, Card...)
│   │   ├── shared/            # 共通コンポーネント (Navbar, Footer...)
│   │   └── chat/              # Chat 用 UI コンポーネント群
│   │
│   ├── features/              # 機能モジュール単位の分割
│   │   ├── auth/
│   │   ├── user/
│   │   └── post/
│   │
│   ├── jotai/                 # グローバル状態 (atoms)
│   │   ├── authAtoms.ts
│   │   ├── uiAtoms.ts
│   │   ├── chatAtoms.ts
│   │   └── index.ts
│   │
│   ├── hooks/                 # 共通カスタム hooks (useTheme, useAuth...)
│   ├── lib/                   # 外部ライブラリや API クライアント
│   ├── styles/                # グローバルスタイルと tailwind 設定
│   │   ├── globals.css
│   │   └── theme.css
│   ├── types/                 # 型定義 (DTO, API 型など)
│   │   └── chat_types.ts
│   ├── utils/                 # 純粋関数ツール
│   └── config/                # 環境変数や定数
│
├── tailwind.config.ts
├── postcss.config.js
├── tsconfig.json
└── package.json

レイヤー構成の考え方

  • pages/: ルーティングに対応。薄い層としてコンテナの呼び出しだけを行う。
  • containers/: 業務ロジックを担い、components にデータを渡す。
  • components/: UI 専用。ロジックを持たず再利用可能。
  • features/: 機能ごとに hooks、service、types をまとめる。
  • jotai/: 全体または複数ページで共有される atoms。特定機能に閉じるものは features/xxx/atoms.ts に配置。

小規模プロジェクトと大規模プロジェクト

  • 小規模: pages/ に直接ロジックを書いてもよい。開発は速いが保守性は低い。
  • 大規模: containers/ を導入し、ロジックを分離するのが望ましい。

コンテナ導入の目安 (ざっくり)

  • ページに書くコードが 200 行を超えて見づらくなる
  • 外部サービスや WebSocket と何度もやり取りする処理が出てくる
  • jotai や recoil などで管理する状態が増えて、複数の atom をまたぐようになる

こういった場面に差し掛かったら、containers/ に切り出して役割を分けるのが無難。

Discussion

MizMiz

bulletproof-reactベースの構成に、Feature-Sliced DesignでいうWidgets層のような役割を持った containersディレクトリが加わったという感じの構成ですね。
比較的学習コストが低いので小規模なプロジェクトでも取り入れやすく、UIとビジネスロジックのコード分離もできるので保守性も保ちやすく良いと思います。

多少学習コストは高くなりますが、プロジェクト規模が大きくなってより厳格にコード分離したい場合は前述のFeature-Sliced Designを採用すると良いかも知れません。