Next.jsのプロジェクト構成とファイルコロケーション

この記事は Next.js公式ドキュメント『[Project Organization and File Colocation](https://nextjs.org/docs/app/building-your-application/routing/colocation) 』の翻訳記事です。

Next.js 公式ドキュメントは[日本語翻訳プロジェクト](https://github.com/Nextjs-ja-translation/Nextjs-ja-translation-docs)がかつてありましたが更新が止まっており、（React・Next.jsアプリケーションの設計について考えたいという動機で）ちゃんと読みたかったこちらの記事を個人的に翻訳しました。

この記事の中で「コロケーション」という用語が繰り返し出てきますが、さまざまなReact関連のドキュメントで言及があり、（旧版）React公式ドキュメントの『[ファイル構成](https://ja.legacy.reactjs.org/docs/faq-structure.html)』、 [Kent C. Dodds 氏](https://kentcdodds.com/)のブログ記事『[Colocation](https://kentcdodds.com/blog/colocation)』（日本語版はこちら 『[コロケーション](https://www.makotot.dev/posts/colocation-translation-ja)』）、[bulletproof-react](https://github.com/alan2207/bulletproof-react/tree/master)の『[Component Best Practices](https://github.com/alan2207/bulletproof-react/blob/master/docs/components-and-styling.md#components-best-practices)』においては、それぞれ次のように言及されています。

> すべて1フォルダに入れるところから始めましょう。そのうち十分に数が増えれば、いくつかのファイルを分離したくなってくるでしょう。そのころには、どのファイルを一緒に編集している頻度が高いのか、十分わかるようになっているでしょう。一般的には、よく一緒に変更するファイルを近くに置いておくのは良いアイディアです。この原則は、「コロケーション」と呼ばれます。
> 
> 引用: [（旧版）React公式ドキュメント ファイル構成](https://ja.legacy.reactjs.org/docs/faq-structure.html)

> コロケーションの概念はこの基本的な原則に集約されます:
> 
> > "可能な限り関連性が高いものの近くにコードを置いてください。"
> 
> こうも言えます: "一緒に変化するものは、合理的な範囲で近くに置くべきです。"と。
> 
> 引用: [コロケーション](https://www.makotot.dev/posts/colocation-translation-ja)

> **Components Best Practices**
> 
> **Colocate things as close as possible to where it's being used（使用箇所のなるべく近くに配置する）**
>
> Keep components, functions, styles, state, etc. as close as possible to the component where it's being used. This will not only make your codebase more readable and easier to understand but it will also improve your application performance since it will reduce redundant re-renders on state updates.（コンポーネント、関数、スタイル、ステートなどは、それらが使用されるコンポーネントのできる限り近くに置きましょう。これにより、コードベースがリーダブルかつ理解しやすくなるだけでなく、ステート更新時の余計な再レンダリングが減るため、アプリケーションのパフォーマンスも向上します。）
>
> 引用: [bulletproof-react Components And Styling](https://github.com/alan2207/bulletproof-react/blob/master/docs/components-and-styling.md#components-best-practices)

以下、翻訳記事となります。

# Next.jsのプロジェクト構成とファイルコロケーション

Next.jsは、[ルーティングフォルダ・ファイル規約](https://nextjs.org/docs/getting-started/project-structure#app-routing-conventions)以外では、プロジェクトのファイルをどのような構成にしコロケーションするかについて、 **何か特定の方法を推奨しているわけではありません**。

このページでは、Next.jsのプロジェクト構成に役立つ、Next.jsのデフォルト動作と機能を紹介します。

- [デフォルトの安全なコロケーション](https://qiita.com/yokoto/items/c3b0145fe0990948e1ec#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AE%E5%AE%89%E5%85%A8%E3%81%AA%E3%82%B3%E3%83%AD%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)
- [プロジェクト構成のための機能](https://qiita.com/yokoto/items/c3b0145fe0990948e1ec#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%A7%8B%E6%88%90%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E6%A9%9F%E8%83%BD)
- [プロジェクト構成の戦略](https://qiita.com/yokoto/items/c3b0145fe0990948e1ec#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%A7%8B%E6%88%90%E3%81%AE%E6%88%A6%E7%95%A5)

---

## デフォルトの安全なコロケーション

`app` ディレクトリ内では、[ネストされたフォルダの階層](https://nextjs.org/docs/app/building-your-application/routing#route-segments) がルート構造を定義します。

`app` ディレクトリ内の各フォルダは、[ルートセグメント（Route Segments）](https://nextjs.org/docs/app/building-your-application/routing#route-segments)です。各ルートセグメントは、URLパス内の対応するセグメントにマップされます。

しかし、フォルダによってルート構造が定義されているにもかかわらず、 `page.js` または `route.js` ファイルがルートセグメントに追加されるまでは、ルートは **公開されていない状態であり、アクセスすることはできません** 。

![project-organization-not-routable.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54467/58c235f1-38a3-37fa-99c9-f45d5d86d7c4.png)

ルートが公開されてアクセスできるようになったとしても、`page.js` または `route.js` によって **返却されるコンテンツ** （`page.js` と `route.js` に記述されている内容）だけがクライアントに送信されます。

![project-organization-routable.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54467/5d3bd164-ca38-90fb-3315-81d8ca772f68.png)

これは、`app` ディレクトリ内の **プロジェクトファイル** が、間違えてルーティング可能になってしまうことがなく、ルートセグメント内で **安全にコロケーションする** ことができるということを意味します。

![project-organization-colocation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54467/4034eaf6-1c18-e386-2ae3-e3c4c32444ca.png)

:::note info
知っておくと良いこと
- これは、App Router の `app` ディレクトリが、Pages Router の `pages` ディレクトリと異なっている点です。Pages Router では `pages` ディレクトリ内のいずれのファイルもルートとして扱われます。
- `app` ディレクトリ内にプロジェクトファイルをコロケーションすることができると話しましたが、これは必須というわけではありません。あなたの好みの方法に応じて、`app` ディレクトリの外にプロジェクトファイルを置いてもよいでしょう。
:::

## プロジェクト構成のための機能

Next.jsは、プロジェクト構成を行うのに役立つさまざまな機能を提供しています。

### プライベートフォルダ（Private Folders）

プライベートフォルダは、フォルダのプレフィックスとしてアンダースコアを付けることで作成できます: `_folderName`

これは、フォルダがプライベートな実装の詳細であり、ルーティングシステムによって考慮されるべきではないということを表します。そのため、 **プライベートフォルダおよびそのすべてのサブフォルダはルーティングから除外されます**。

![project-organization-private-folders.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54467/09c93570-2d2d-3cfe-4137-9d198443b4fb.png)

`app` ディレクトリ内のファイルは [デフォルトで安全にコロケーションする](https://nextjs.org/docs/app/building-your-application/routing/colocation#safe-colocation-by-default) ことができるため、コロケーションのためにプライベートフォルダにすることが必須なわけではありません。しかし、プライベートフォルダは以下の目的のために役立つでしょう：

- UIのロジックとルーティングのロジックを分離したいとき
- プロジェクトとNext.jsのエコシステムにおいて内部ファイルを一貫した方法で整理したいとき
- コードエディタ上でファイルをソートしたりやグルーピングしたいとき
- 将来的なNext.jsのファイル規約と命名がコンフリクトする可能性を回避したいとき

:::note info
知っておくと良いこと
- フレームワークの規約とは関係ありませんが、プライベートフォルダの外のファイルでも同じようにアンダースコアを使ってそれを「プライベートなファイルである」として扱ってもよいでしょう。
- アンダースコアで始まるURLセグメントを作成するには、フォルダ名の前に `%5F` （アンダースコアのURLエンコード形式）を付けてください: `%5FfolderName` 。
- プライベートフォルダを使用しない場合、偶然の命名のコンフリクトを防げるように、Next.jsの[特別なファイル命名規則](https://nextjs.org/docs/getting-started/project-structure#routing-files)を知っておくとよいでしょう。
:::

### ルートグループ（Route Groups）
ルートグループは、フォルダを括弧で囲むことで作成できます: `(folderName)`。

これは、そのフォルダは構成を表すという目的のために使用されているのでルートのURLパスには **含めるべきではない** 、ということを示しています。

![project-organization-route-groups.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54467/853ec0b5-abaa-c5d0-0142-0cf94ad54d5a.png)

ルートグループは以下の目的のために役立つでしょう：

- [ルートをグループに整理する](https://nextjs.org/docs/app/building-your-application/routing/route-groups#organize-routes-without-affecting-the-url-path)ため。例: サイトのセクション単位、目的単位、チーム単位など。
- 同じルートセグメントレベルでのネストされたレイアウトを有効にする：
    - [同じセグメント内で複数のネストされたレイアウト（複数のルートレイアウトを含む）を作成したいとき](https://nextjs.org/docs/app/building-your-application/routing/route-groups#creating-multiple-root-layouts)
    ![route-group-multiple-root-layouts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54467/e070f47e-b0a6-b494-8fb5-a109d840c8ec.png)
    - [共通のセグメント内のルートのサブセットにレイアウトを追加したいとき](https://nextjs.org/docs/app/building-your-application/routing/route-groups#opting-specific-segments-into-a-layout)
    ![route-group-opt-in-layouts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54467/081d5366-1973-46a3-5bc1-410052b59dee.png)


### srcディレクトリ

Next.jsは、アプリケーションコード（`app` を含む）をオプションの [`src` ディレクトリ](https://nextjs.org/docs/app/building-your-application/configuring/src-directory)内に置くことをサポートしています。これにより、アプリケーションコードは、主にプロジェクトルートに存在するプロジェクトの設定ファイルと分離されます。

![project-organization-src-directory.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54467/76d743e5-edff-68c0-a430-74e3529f6015.png)

### モジュールパスエイリアス（Module Path Aliases)

Next.jsは、深くネストされたプロジェクトファイル全体でのインポートを読みやすく保守しやすくするための[モジュールパスエイリアス](https://nextjs.org/docs/app/building-your-application/configuring/absolute-imports-and-module-aliases)をサポートしています。

```app/dashboard/setting/analytics/page.js
// before
import { Button } from '../../../components/button'
 
// after
import { Button } from '@/components/button'
```

## プロジェクト構成の戦略

Next.jsプロジェクトでフォルダ・ファイル構成の方法について話すとき、「正しい」方法や「間違った」方法というものはありません。

以下のセクションでは、一般的な戦略の超概要レベルだけをいくつか示しています。最も基本的かつ簡潔なポイントとしては、あなたやあなたのチームに合った戦略を選び、それがプロジェクト全体で一貫している、ということです。

:::note info
知っておくと良いこと
- 下記の例では、`components` や `lib` フォルダを一般的なプレースホルダとして使用していますが、これらの命名がNext.jsフレームワークにおいて特別な機能や役割を持っているわけではありません。あなたのプロジェクトでは、`ui`、 `utils`、 `hooks` 、 `styles` など他のフォルダを使用するかもしれません。
:::

### `app` の外にプロジェクトファイルを置く

この戦略では、すべてのアプリケーションコードを **プロジェクトルート** の共有フォルダに置き、appディレクトリは単なるルーティング目的のためだけに使用します。

![project-organization-project-root.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54467/0853d33c-0d8c-8bac-3959-24125a17c4d5.png)

### `app` のトップレベルフォルダ内にプロジェクトファイルを置く

この戦略では、すべてのアプリケーションコードを **`app` ディレクトリルート** の共有フォルダに置きます。

![project-organization-app-root.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54467/10662417-bfcc-c906-70d8-6cf8ff2af160.png)

### 機能やルートごとにプロジェクトファイルを分割する

この戦略では、グローバルに共有されるアプリケーションコードを `app` ディレクトリルートに置き、それを使用するルートセグメントにより特定のアプリケーションコードを **分割** します。

![project-organization-app-root-split.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54467/efaa0c2f-e983-d27c-21b3-94ab964d57aa.png)