【06】Next.js14でTodoアプリ作成(ディレクトリ構成修正編)

# はじめに

ディレクトリのベストプラクティスを知らずに、適当に開発してきたため、今一度ディレクトリ構成を見直すことにしました。

<details><summary>今までの記事</summary>

環境構築編 

https://qiita.com/naoyuki2/items/e974c630c6cbd3c55254

【01】Next.js14でTodoアプリ作成(CREATE編)

https://qiita.com/naoyuki2/items/7474d448de7769905d82

【02】Next.js14でTodoアプリ作成(SELECT編)

https://qiita.com/naoyuki2/items/2d8ad09f767f818e8860

【03】Next.js14でTodoアプリ作成(INSERT編)

https://qiita.com/naoyuki2/items/27d550ab3766a1869aaf

【04】Next.js14でTodoアプリ作成(DELETE編)

https://qiita.com/naoyuki2/items/8fcb8ae5583a1aef8a2d

【05】Next.js14でTodoアプリ作成(UPDATE編)

https://qiita.com/naoyuki2/items/2d90cc092570dd5e6b73

</details>

### 今回のゴール

色々な記事を読んだ結果私は以下のようなディレクトリ構成にしました。

```
.
├── components/
│   ├── elements/
│   │   ├── Button.tsx
│   │   └── Input.tsx
│   └── layouts/
│       ├── Header.tsx
│       └── Footer.tsx
├── features/
│   └── todo/
│       ├── api/
│       │   ├── getTodo.ts
│       │   ├── postTodo.ts
│       │   ├── deleteTodo.ts
│       │   ├── patchTodo.ts
│       │   └── Index.ts
│       └── components/
│           ├── TodoInput/
│           │   └── TodoInput.tsx
│           ├── TodoList/
│           │   └── TodoList.tsx
│           ├── TodoItem/
│           │   └── TodoItem.tsx
│           └── Index.ts
└── src/app/
    ├── api/
    │   ├── lib/
    │   │   └── prisma.ts
    │   └── todo/
    │       ├── [id]/
    │       │   └── route.ts
    │       └── route.ts
    ├── favicon.ico
    ├── global.css
    ├── layout.tsx
    └── page.tsx
```

# １．componentsディレクトリ

```
├── components/
│   ├── elements/
│   │   ├── Button.tsx
│   │   └── Input.tsx
│   └── layouts/
│       ├── Header.tsx
│       └── Footer.tsx
```

ルートディレクトリ直下に作成した`/components`では、アプリケーション全体で使用されるコンポーネントを配置しています。

> このレイヤーでは、副作用を持たずに親から受け取ったpropsのみを表示することに特化しています。
> 状態の受け取りに対して、条件分岐やクラスの付与などを行うことは問題ありません。

https://note.com/ryoppei/n/n2e3e7a66e758

### /components/elements

```
├── elements/
│   ├── Button.tsx
│   └── Input.tsx
```

ここでは、ページ全体で使用する小さい部品、いわゆる`Button`や`Input`などを格納するディレクトリです。

### /components/layouts

```
└── layouts/
    ├── Header.tsx
    └── Footer.tsx
```

ここでは、ページ全体で共通するレイアウト、いわゆる`Header`や`Footer`を格納するディレクトリです。

# ２．featuresディレクトリ

```
├── features/
│   └── todo/
│       ├── api/
│       │   ├── getTodo.ts
│       │   ├── postTodo.ts
│       │   ├── deleteTodo.ts
│       │   ├── patchTodo.ts
│       │   └── Index.ts
│       └── components/
│           ├── TodoInput/
│           │   └── TodoInput.tsx
│           ├── TodoList/
│           │   └── TodoList.tsx
│           ├── TodoItem/
│           │   └── TodoItem.tsx
│           └── Index.ts
```

`features`は特定の機能をもっているコンポーネントをまとめるためのディレクトリです。

例に挙げている、TodoInputなどは、アプリケーション全体で再利用できるとは言えず、`/components`にいれず、`features`を用意しています。

`features`は日本語で`特徴`という意味なので、特徴あるコンポーネントを格納することから名付けけられたのではないでしょうか。

### /features/todo/api

```
api/
│── getTodo.ts
│── postTodo.ts
│── deleteTodo.ts
│── patchTodo.ts
│── Index.ts
```

ここでは、`todo`に関する`API`をたたくための関数を格納しています。

[前回](https://qiita.com/naoyuki2/items/2d90cc092570dd5e6b73)の記事の`page.tsx`を見てもらえればわかると思いますが、`API`をたたくだけでもかなり記述量が増えてしまっていたためこのようにしました。

[`Index.ts`]()については後程解説します。

### /features/todo/components

```
       └── components/
           ├── TodoInput/
           │   └── TodoInput.tsx
           ├── TodoList/
           │   └── TodoList.tsx
           ├── TodoItem/
           │   └── TodoItem.tsx
           └── Index.ts
```

ここでは、`todo`に関する`コンポーネント`を格納しています。

コンポーネントごとにフォルダを用意しているのは、その中に`.styled.tsx`や`.test.tsx`や`stories.tsx`などを入れる可能性があるからだそうです。

私はテストもストーリーブックも分かりません。

ここでも`Index.ts`がでてきます。次で解説します。

### Index.ts

おまちかね`Index.ts`の解説です。

意図としては、下記の記事のお言葉をお借りして説明させていただきます。

※`products`は`todo`で置き換えてください。

> ● このファイルは、products関連のコンポーネントを一括でインポートするためのエントリーポイントとなります。
● コンポーネントのインポートパスを短くすることで、コードの可読性を向上させます。
● 他のファイルからこのエントリーポイントを通じてproductsコンポーネントにアクセスすることができます。
● 新しいproductsコンポーネントが追加された場合でも、このファイルの変更のみで済みます。

https://note.com/ryoppei/n/n2e3e7a66e758

コード例を紹介すると以下の通りです。

```ts:features/todo/componentsIndex.ts
import TodoInput from './TodoInput/TodoInput'
import TodoList from './TodoList/TodoList'
import TodoItem from './TodoItem/TodoItem'

export { TodoInput, TodoList, TodoItem }
```

```tsx:src/app/page.tsx
import * as Todo from '@features/todo/components/Index'

export default function Home() {
    return (
        <>
            <Todo.TodoInput />
            <Todo.TodoList />
        </>
    )
}
```

`Index.ts`でまとめてエクスポートしています。

そして、使用するページで`* as Todo`とすることで、`Todo.TodoInput`という風に使用します。

`import`するデータ量は増えてしまいますが、かなりわかりやすくなりますし、`import`文は一つで済みます。

`API`をたたく関数も`Index.ts`を使用して`import`しています。

# ３．src/appディレクトリ

```
└── src/app/
    ├── api/
    │   ├── lib/
    │   │   └── prisma.ts
    │   └── todo/
    │       ├── [id]/
    │       │   └── route.ts
    │       └── route.ts
    ├── favicon.ico
    ├── global.css
    ├── layout.tsx
    └── page.tsx
```

私はプロジェクトを作る際に`src`フォルダの有無を有りにしたので、`src`フォルダがありますが、別にいらないような気がします。

ここはそんなに解説することはないですね。

# おわりに

このディレクトリ構成が一番！なんてものはないと思いますが、私は個人開発ではこのディレクトリ構成で開発を進めようと思います。

次回以降はまたロジックを実装していきます。

# 参考文献

https://nextjs.org/docs/app/building-your-application/routing/colocation

https://note.com/ryoppei/n/n2e3e7a66e758

https://youtu.be/ekUQ043k2TQ?si=ELmnwJrKelxKVdp5