はじめに
あけましておめでとうございます。
今回は、私なりに色々考えた中規模程度のReactプロジェクトを開発する際のディレクトリ構成について書いていきたいと思います。
前提となる環境・パッケージなど
開発環境
- React 18.2.0
- TypeScript 4.9.5
ディレクトリ構成に影響のあるパッケージ
- Recoil (状態管理)
- React-hooks-form・zod (入力フォームの状態管理とバリデーション)
- React-router-dom (ルーティング)
ディレクトリ構成図
└── src
├── features
│ └── Auth
│ ├── hooks // Auth/Pagesで使われる自作のhooks
│ │ ├── useLogin.ts
│ │ └── useRegister.ts
│ ├── components //Auth/Pages内でしか使われないコンポーネントを置く
│ │ └── PasswordForm
│ │ ├── PasswordForm.tsx
│ │ ├── PasswordForm.stories.tsx
│ │ └── passwordForm.module.css
│ ├── pages
│ │ ├── Login
│ │ │ ├── LoginPage.tsx // コンポーネントを組み合わせたPage全体の状態、レイアウトを記述する
│ │ │ └── loginPage.css.module.css
│ │ └── index.ts // Auth/Pagesの中のPageを一括でエクスポート
│ ├── (atom.ts) // RecoilのAtomを管理
│ ├── (selector.ts) // 同じくSelectorを管理
│ ├── (auth.constant.ts) // ドロップダウンメニューの項目など定数を保管
│ ├── (auth.type.ts) // AuthのPage内でしか使われないType(interface)を保管
│ └── (auth.validation.ts) // zodのバリデーションスキーマを保管
├── components
│ ├── elements // 汎用的なコンポーネント
│ │ ├── Button
│ │ │ ├── Button.tsx
│ │ │ ├── button.module.css
│ │ │ └── button.stories.tsx
│ │ ├── TextField
│ │ │ ├── TextField.tsx
│ │ │ ├── textField.module.css
│ │ │ └── textField.stories.tsx
│ │ └── index.ts // elements配下のコンポーネントを一気にexport
│ └── layouts // 汎用的なレイアウトされたコンポーネント
│ └── NavigationBar
│ └── NavigationBar.tsx
│ └── navigationBar.module.css
├── routes
│ └── index.ts // pagesのエクスポートをまとめて、ログインしてるかそうでないかで分けた<Routes/>をエクスポート
└── common
├── types // 型情報を管理
│ └── user.ts
├── utils // 汎用的に使える関数を管理
│ └── localStorageManager.ts
└── messages.ts // バリデーションのメッセージなどを格納
こちらの構成図はAscii Tree Generatorを使用しました😎
では、要点の解説をしていきます。
features
機能ごとにディレクトリを切ります。
ログインや新規登録などであれば/Auth
、プロフィール登録、表示などであれば/User
のようにします。
()がついているファイルは、必要な時のみ作成するものです。
features/〇〇/pages
〇〇の機能に属するページ全体のUIを記述した.tsx
ファイルを置きます。
/Auth
であれば、ログイン画面や新規登録のUIを記述したファイルを置きます。
features/〇〇/pages/index.ts
pages
以下のページをまとめてエクスポートします。
features/〇〇/hooks
自作のhooksを置いておきます。/Auth
であるならuseLogin
、useLogout
などです。
features/〇〇/components
その機能でしか使われないコンポーネントを置いておきます。
パスワードを入力するのに特化したTextFieldなど、汎用的でなく、機能が限定されたコンポーネントをここに入れます。
components/elements
ButtonやTextFieldなどの汎用的なコンポーネントをおきます。複数のfeaturesを跨いで使用するコンポーネントと言い換えてもいいです
components/layout
上記のcomponents/elements
を組み合わせた、汎用的なコンポーネントをおきます。
ヘッダーやフッターなどが該当します。
routes
features/〇〇/pagesでエクスポートされたページを集めて、ログイン、非ログインなどの状態により分けられたをエクスポートします。
common
汎用的に使用される型情報、定数、バリデーションメッセージ、ユーティリティ関数などを格納しています。
まとめ
わりとわかりやすい形にまとめられたと思います。
現状これで困っていることはあまりないですが、また変更があれば追記していこうと思います。
また、ここはこうした方がいいなどご意見あればぜひお願いしたいです!(実は半分それが目的で記事を書きました)質問等も遠慮なくしていただければと思います。
では、ここまでお読みいただきありがとうございました!