フルスタックNext.jsアプリケーションのディレクトリ構成 | Pathee Advent Calendar 2021 Day 3
これはPathee Advent Calendarの3日目の記事です
こんにちは。土田です。
前回STORECAST Managerのお話をさせていただきましたが、
今回は、フルNext.jsのアプリケーションで、どういったディレクトリ構成を取って開発しているのかをお話させていただきます。
ディレクトリ構成
早速ですが、Next.jsアプリケーションのプロジェクト配下でtree出力した、主要なディレクトリは以下になります。
. ├── infra │ ├── docker │ └── mysql │ ├── conf.d │ ├── original │ └── sql ├── public │ └── static │ ├── fonts │ └── images └── src ├── @types ├── assets ├── components │ ├── gui │ │ ├── alerts │ │ ├── atoms │ │ ├── buttons │ │ ├── forms │ │ └── tables │ ├── layouts │ └── pages ├── constants ├── hooks ├── libs ├── pages │ ├── api │ │ ├── auth │ │ ├── manager │ │ └── st │ ├── auth │ └── manager ├── server │ ├── domains │ │ └── manager │ ├── entities │ │ ├── manager │ │ └── st │ │ └── XXXX │ ├── migrations │ │ └── manager │ ├── repositories │ │ ├── manager │ │ └── st │ │ └── XXXX │ └── subscribers │ └── manager ├── states ├── styles └── utils
役割ごとに色分けをすると、このようになります。
順に役割を上げていきます。
1. 開発用インフラ設定の各ディレクトリ
上から話していくと、一番アプリケーションと縁遠いディレクトリからになってしまってあれですが、 infraディレクトリはローカル開発で利用するインフラの設定を配置しています。
docker
dockerディレクトリにはdocker-compose.ymlから見るenv_fileを配置しています。
Next.jsはローカル起動用の環境変数を、ルートディレクトリに配置した.env.local
ファイルから読み取ってくれるのですが、
.env.local
ファイルはリポジトリ管理しないファイルにしているので、これをenv_fileに指定していると、
git cloneの後、無邪気にdocker compose up -d
を実行すると、起動に失敗してしまいます。
それはそれで良い気もしますが、.env.local
ファイルを作るためのアプリケーション用環境変数ファイル(.env
)には、コンテナ自体に必要な環境変数が書かれているわけでもないと思うので、
起動前に読み込む環境変数ファイルは別管理にしました。
ちなみに起動用のファイル(infra/docker/.env.dev
)の内容は、以下の通りです。
NODE_ENV="development" REACT_EDITOR=atom
mysql
mysqlディレクトリは、mysqlコンテナから読み込む各種ファイルを置いておく場所として利用しています。
2. フロントエンド用ディレクトリ
Next.jsは元々フロントエンド用のフレームワークなので、他は大体フロントエンド用になっています。
Next.js関連のディレクトリについて
publicディレクトリは、Next.jsで静的ファイルを配信する場合に利用するディレクトリです。
nextjs-ja-translation-docs.vercel.app
srcディレクトリ配下のpages、stylesもNext.js関連のディレクトリなため、それ以外について説明していきます(stylesは必須なわけではありませんが)。
@types
型定義用のディレクトリです。
主にAPIコールで受け渡しに利用する型など、複数箇所から利用する型を定義するのに利用しています。
assets
next/image
で遅延読み込みする画像ファイルなどを配置する場所として利用しています。
components
さて、componentsディレクトリですが、大きく3つの用途で利用しています。
現状ではAtomic Designの構成は冗長で、利用しづらいと判断したため、このような構成になっています。
components/gui
guiディレクトリの中は、大まかなタグ要素で分類しています。
例えば、input要素はformsに、ボタン系はbuttonsに配置し、各ディレクトリにinput.tsを置いて、
export * from './SaveButton';
のような記載をしています。
あまり使わないですが、各パーツから共通的に参照する可能性のある最小のパーツは、atomsディレクトリに配置するようにしています。
components/layouts
layoutsディレクトリは、ページで共通で利用するレイアウトのためのディレクトリです。
アプリケーションの標準レイアウトはlayouts直下で、それ以外の個別レイアウトは更にサブディレクトリを切って管理しています。
mainディレクトリを切ってもよかったかなぁとは思います。
STORECAST Managerでは例えば以下のようにレイアウトが異なるため、それぞれ分けて持つようにしています。
layouts/index.tsの適用例
layouts/auth/index.tsの適用例
components/pages
src/pages
配下で利用する、各ページ専用のコンポーネントを配置する場所としています。
サブディレクトリは、src/pagesディレクトリと同じような切り方をするようにしています。
例えば、src/pages/st/accounts/[id]
用のpagesディレクトリは、src/components/pages/st/accounts/[id]
になっています。
constants
アプリケーションで利用する定数を定義する場所として利用しています。
hooks
カスタムフックを配置するディレクトリです。
libs
主に環境変数を利用する、ライブラリの設定処理を記載しています。
states
recoilで利用するstateを配置するディレクトリです。
utils
汎用的なユーティリティ処理を配置するディレクトリです。
3. バックエンド用ディレクトリ
serverディレクトリは、src/pages/api
配下の処理で使われる、バックエンド用のコードディレクトリです。
domains
src/pages/api
から直接呼び出されるのは、このdomains配下のみになるように実装しています。
例えば、pages/api/accountsから呼び出されるのは、domains/accounts.ts
のようにして利用しています。
repositories
順番が前後しますが、repositoriesディレクトリはDBへのアクセス処理を書く場所として利用しています。
repositories直下のディレクトリはDB名で、その配下にテーブル名のコードを配置しています。
- 例:
src/server/repositories/manager/account.ts
であれば、managerDBのaccountテーブル
STORECAST自体は複数のDBを持つので、stディレクトリ配下に更にDB名でサブディレクトリを切る構成にしています。
entities、migrations、subscribers
entities、migrations、subscribersはTypeORM関連のディレクトリです。
公式ドキュメントそのままの場合は、entity/migration/subscriberですが、プロジェクト内の他のディレクトリに合わせて複数形にしています。
まとめ
以上が現状のディレクトリ構成になっています。 アプリケーションを作っていくうちに、また構成が変わるかもしれませんが、最初の段階としては管理しやすいのでおすすめです。