小さくはじめる Next.js App Router ディレクトリ構成 「featuresでコンポーネントを整理する」

# はじめに
最近自分がNext.jsの環境構築、設計を担当する機会が増えました。
ディレクトリ構成が固まってきたので一つの案として参考になれば幸いです。

# こんな方におすすめ！
- Next.js App Routerを使って小規模開発(個人開発含む)を行いたい方
- Next.js App Routerに関してなんとなく理解したけどディレクトリ構成で迷ってる方
- featuresになんとなく興味のある方

# 目次
- [featuresとは何か](#featuresとは何か)
- [構成案](#構成案)
- [appディレクトリ](#appディレクトリ)
- [featuresディレクトリ](#featuresディレクトリ)
- [componentsディレクトリ](#componentsディレクトリ)
- [hooksディレクトリ](#hooksディレクトリ)
- [utilsディレクトリ](#utilsディレクトリ)
- [constantsディレクトリ](#constantsディレクトリ)
- [実際に実装してみて](#実際に実装してみて)

# featuresとは何か
アプリケーション内で独立した機能として識別できる要素のこと。
中にはUIコンポーネント、ロジック、スタイルなどが入る。
1行でまとめるのであれば
**ロジックのあるコンポーネントはfeaturesを見れば大体把握できる**
という認識かなと思います。

# 構成案
以下構成はsrcディレクトリ内と想定します。
srcを使わない場合はルートディレクトリに記述するものとします。
```console:ディレクトリ構成
├── app          ... ルーティングに関するコンポーネント
├── features     ... ロジック + コンポーネントをまとめたもの
│   ├── common   ... 共通部分
│   └── routes   ... 特定のページで使うもの
├── components   ... ロジックがない共通コンポーンネント
├── hooks        ... 共通ロジックの内、React Hooksが「ある」もの
├── utils        ... 共通ロジックの内、React Hooksが「ない」もの
└── constants    ... 定数を定義したファイル
```
※treeは説明順に記載してます


# appディレクトリ
ルートページに関することを記述。
appディレクトリでは"use client"を記述しない方向性。
つまりuse〇〇といったhooksは使わないのでServer Componentだけになります。


**appディレクトリに記述するもの**
- Server Sideでデータをfetchするコンポーネント
- ロジックを含まない見た目だけを実装するコンポーネント。以下例
    - テキスト
    - 見た目だけのDOM
    - リンク


```console:appディレクトリサンプル(ブログサイトを想定)
├── blog
│   ├── [uuid]
│   │   └── page.tsx
│   │       └── edit
│   │           └── page.tsx
│   ├── create
│   │   └── page.tsx
│   └── page.tsx
├── login
│   └── page.tsx
├── profile
│   └── page.tsx
```

# featuresディレクトリ
今回の目玉とも言えるディレクトリ。
**ロジック+コンポーネントのファイルは全てfeaturesディレクトリの中に記述します。**
基本的にはappディレクトリから呼び出されることになります。

```console:featuresディレクトリサンプル(ブログサイトを想定)
├── common
│   ├── editors
│   │   ├── components
│   │   │   ├── CodeEditor.tsx
│   │   │   └── RichTextEditor.tsx
│   │   ├── hooks.ts
│   │   └── stores.ts
│   ├── forms
│   │   ├── components
│   │   │   ├── Input.tsx
│   │   │   └── Select.tsx
│   │   ├── hooks.ts
│   │   └── stores.ts
│   └── tags
│       ├── components
│       │   ├── TagItem.tsx
│       │   └── TagList.tsx
│       ├── hooks.ts
│       └── stores.ts
└── routes
    ├── auth
    │   ├── components
    │   │   └── Login.tsx
    │   ├── endpoint.ts
    │   └── hooks.ts
    ├── post
    │   ├── detail
    │   │   ├── components
    │   │   │   ├── Contents.tsx
    │   │   │   └── Suggests.tsx
    │   │   ├── endpoint.ts
    │   │   ├── hooks.ts
    │   │   └── stores.ts
    │   └── list
    │       ├── components
    │       │   ├── List.tsx
    │       │   ├── Search.tsx
    │       │   └── Tabs.tsx
    │       ├── endpoint.ts    
    │       ├── hooks.ts
    │       └── stores.ts
    └── profile
        ├── components
        │   ├── Email.tsx
        │   └── Password.tsx
        ├── endpoint.ts
        ├── hooks.ts
        └── stores.ts
```

## features/commonディレクトリ
複数のページで使われるロジック込みの共通コンポーネント。
主に以下のものになります(ブログサイトを想定した場合)

- フォーム
- エディタ
- タグ
など


## features/routesディレクトリ
1つのページ種類で使われるロジック込みの非・共通コンポーネント。
主に以下のものになります(ブログサイトを想定した場合)

- ログイン
- 投稿一覧
- 投稿詳細
- 投稿画面
- プロフィール
など

## features内のディレクトリ・ファイルについて
### componentsディレクトリ
見た目部分をまとめたディレクトリ
ロジックに関してはhooks.tsに記述する
### endpoint.tsファイル
APIを実行エンドポイントを記載。
ここには基本的にfetchやaxiosといったものだけを記載する
### hooks.tsファイル
コンポーネントの内、ロジックを記載
### stores.tsファイル
ファイル間を跨いだstateを管理。
1ファイル内で完結するstate管理のみuseStateを使用する。

# componentsディレクトリ
ロジックがない共通コンポーンネント。
あらゆるページで使用できるUIに関することを記述します

```console:componentsディレクトリサンプル
├── Alert.tsx
├── Button.tsx
├── Label.tsx
├── Logo.tsx
├── Menu.tsx
└── Modal.tsx
```

# hooksディレクトリ
共通ロジックの内、React Hooksが「ある」ものを記述。
ここには共通ロジックしか記述しないので、特定のページ群(ブログサイトであれば投稿関連画面など)でしか使わないReact Hooksに関してはfeaturesディレクトリに記述します。
React Hooksの説明は公式ドキュメントがわかりやすいです。

https://ja.react.dev/reference/react/hooks

```console:hooksディレクトリサンプル
├── useRedirect.ts
├── useSave.ts
├── useSearch.ts
├── useToast.ts
└── useWidthSize.ts
```

# utilsディレクトリ
共通ロジックの内、React Hooksが「ないもの」ものを記述。
例えば特定の文字を整形して変換したり、特定の値を日本語に変換するなど。
記述の記述場所に困った時は大体ここに書くことが多そうです。

```console:utilsディレクトリサンプル
├── dates.ts
├── formats.ts
└── validation.ts
```

# constantsディレクトリ
定数を定義したファイル。
colorコードや都道府県selectBoxなどを管理することが多そうです。
```console:constantsディレクトリサンプル
├── options.ts
├── paths.ts
└── styles.ts
```

# 実際に実装してみて
方針としてはルールはあまり決めずに設置場所は開発者に任せようぜ！というスタンスかなと思います。
迷わないというメリットはありつつ、ルールがないからこそ、開発者によって認識齟齬が発生するというデメリットもあるかなと思います。例えばどこからcommon(共通)になるのか？、同じendpointを複数ページで実行する場合どこに記述するか？ などです。
スモールスタートでNext.jsを使う場合はとにかく手を動かしてトライアンドエラーを繰り返すのがいいかなと思います。
最後までお読みいただきありがとうございます！