7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Next.js13】appDirでコロケーション化

Last updated at Posted at 2023-09-28

2023年5月にappDirがStatable版となった Next.js13.4 を社内プロジェクトで使用することになりました。
appDirではコロケーション化に適したディレクトリ構成が可能です。

Next.js12以前は主流だったpagesDirのディレクトリ構成では、pages/配下にファイルを置くことでページ扱いとなっており、pages/配下にページファイル以外のものを置くことはできません。

// ページ以外のファイルは置いちゃダメ
├─pages
|   ├─pageA.jsx
|   └─...

したがって、hogehoge.com/pageでしか使用しないコンポーネントがあったとしたら、大体の人がcomponentsディレクトリを作成してその配下にhome/componentA.jsxみたいなディレクトリ構成を試みるのではないでしょうか。

├─pages
|   ├─pageA.jsx
|   └─...
├─components
|   ├─pageA
|   |   ├─componentA.jsx
|   |   └─...

それがappDirの構成だとコロケーション化が望めるわけです。

├─app
|   ├─pageA
|   |   ├─page.jsx
|   |   ├─_components
|   |   |   ├─componentA
|   |   |   |   ├─index.jsx
|   |   |   |   └─...
|   |   |   └─...

appDirの構成の場合、app/配下の route directory 内でプライベートディレクトリを作る時は_components のようにアンダースコアをつければプライベートディレクトリとみなされるのでこれがコロケーション化を捗らせます。
TypeScriptの場合、homeページでしか使用しない型定義ファイルなんかも

├─app
|   ├─pageA
|   |   ├─page.jsx
|   |   ├─_components
|   |   |   ├─componentA
|   |   |   |   ├─index.jsx
|   |   |   |   └─...
|   |   |   └─...
|   |   ├─_types
|   |   |   ├─typeA.ts
|   |   |   └─...

ただ、ドメインルートのページでのみ使用したいあれこれが出てきた時に...

├─app
|   ├─_components
|   |   ├─componentA
|   |   |   └─index.tsx
|   |   |   └─...
|   |   └─...
|   ├─_types
|   |   └─types.ts
|   ├─pageA
|   |   ├─page.tsx
|   |   ├─_components
|   |   |   └─componentA
|   |   |       ├─index.tsx
|   |   |       └─...
|   |   └─_types
|   |       └─types.ts
|   └─page.tsx

こうなる。
見づらいしドメインルートのページでしか使わないようには見えない。
この問題を解決するために

├─app
|   ├─(root)
|   |      ├─page.tsx
|   │   ├─_components
|   │   │   └─componentA
|   │   │   │   ├─index.tsx
|   │   │   │   └─...
|   │   │   └─...
|   │   └─_types
|   |       ├─types.ts
|   |       └─...
|   ├─pageA
|   │   ├─page.tsx
|   │   ├─_components
|   │   │   └─componentA
|   │   │       ├─index.tsx
|   │   │       └─...
|   │   └─_types
|   │      ├─types.ts
|   │      └─...
    

のように(root)ディレクトリを作ることでURLに影響を与えることなくドメインルートのページをグルーピングできました。

汎用コンポーネントはapp/と同じ階層にcomponents/ディレクトリを作成してそこに置くようにしました。
汎用コンポーネントなのかコード分割用コンポーネントなのかをディレクトリ構成でわかるのは便利です。
(使い回す型定義などあればtypes/ディレクトリを作ったり)

styleシートやStoryBookやtestコードも入れちゃいます。

【完成系】

├─app
|   ├─(root)
|   |      ├─page.tsx
|   │   ├─_components
|   │   │   └─componentA
|   |   │       ├─index.tsx
|   |   │       ├─index.module.css
|   |   │       ├─index.stories.tsx
|   |   │       └─index.test.tsx
|   │   └─_types
|   |       └─types.ts
|   └─pageA
|       ├─page.tsx
|       ├─_components
|       │   └─componentA
|       │       ├─index.tsx
|       │       ├─index.module.css
|       │       ├─index.stories.tsx
|       │       └─index.test.tsx
|       └─_types
|          └─types.ts
├─components
|   └─Button
|          ├─index.tsx
|          ├─index.module.css
|          ├─index.stories.tsx
|          └─index.test.tsx
├─types
|   └─apiType.ts

こんな感じ

すっきりしました

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?