##現状のファイル・フォルダ構成
現状こんな感じの構成(フォルダの種類や構成は少し省略しています。Next.jsのプロジェクトです。)
src
│
├─atoms//atomsに関連するファイルもののみを入れるフォルダ
│ ├─hooks//atomで使用するカスタムフック
│ │ ├─useAtomA.ts
│ │ ├─useAtomB.ts
│ │ └─useAtomC.ts
│ └─styles//atomで使用するcss-module
│ │ ├─atomA.module.scss
│ │ ├─atomB.module.scss
│ │ └─atomC.module.scss
│ ├─AtomA.tsx
│ ├─AtomB.tsx
│ └─AtomC.tsx
│
├─molecules//moleculesに関連するもののみを入れるフォルダ
│ ├─hooks//moleculeで使用するカスタムフック
│ │ ├─useMoleculeA.ts
│ │ ├─useMoleculeB.ts
│ │ └─useMoleculeC.ts
│ └─styles//moleculeで使用するcss-module
│ │ ├─moleculeA.module.scss
│ │ ├─moleculeB.module.scss
│ │ └─moleculeC.module.scss
│ ├─MoleculeA.tsx
│ ├─MoleculeB.tsx
│ └─MoleculeC.tsx
│
├─organisms//organismsに関連するもののみを入れるフォルダ
│ ├─hooks//organismsで使用するカスタムフック
│ │ ├─useOrganismA.ts
│ │ ├─useOrganismB.ts
│ │ └─useOrganismC.ts
│ └─styles//organismsで使用するcss-module
│ │ ├─organismA.module.scss
│ │ ├─organismB.module.scss
│ │ └─organismC.module.scss
│ ├─OrganismA.tsx
│ ├─OrganismB.tsx
│ └─OrganismC.tsx
│
├─pages
│ └─index.tsx
├─hooks//pages内コンポーネントで使用するカスタムフック
│ └─useIndex.ts
├─styles//pages内コンポーネントで使用するcss-module
│ └─index.module.scss
│
└─utils//共有・共通する処理・カスタムフック・スタイル・定数等入れる
改善案
現在のプロジェクトのコンポーネント数は約50個。
ここで、共有するカスタムフックやcss-moduleよりも、一つのコンポーネントにしか使われないカスタムフックやcss-moduleの方が圧倒的に多い。
どのカスタムフックやcss-moduleがどのコンポーネントのものなのか特定するのがめんどくさく、上記の理由もあり、一つのコンポーネントにしか使われていないカスタムフックとcss-moduleの命名は、
カスタムフック名:use{コンポーネント名}
css-module名:{先頭を小文字にしたコンポーネント}.module.scss
としていた。
そこで、大抵カスタムフック・css-moduleとコンポーネントは上記の現状のファイル・フォルダ構成のように、1対1の関係として見れるのではと考えた。
新しいファイル・フォルダ構成
atoms、molecules、organismsで絞るのではなく、さらに一コンポーネントで絞ってフォルダを作成しコンポーネント、カスタムフック、css-moduleをその中に作成する。
(変更部分のみ抜粋)
src
│
├─atoms
│ ├─AtomA//AtomAコンポーネントに関連するファイルのみを入れるフォルダ
│ │ ├─AtomA.tsx
│ │ ├─useAtomA.ts
│ │ └─atomA.module.scss
│ ├─AtomB//AtomBコンポーネントに関連するファイルのみを入れるフォルダ
│ │ ├─AtomB.tsx
│ │ ├─useAtomB.ts
│ │ └─atomB.module.scss
│ └─AtomC//AtomCコンポーネントに関連するファイルのみを入れるフォルダ
│ │ ├─AtomC.tsx
│ │ ├─useAtomC.ts
│ │ └─atomC.module.scss
│
├─molecules
│ ├─MoleculeA//MoleculeAコンポーネントに関連するファイルのみを入れるフォルダ
│ │ ├─MoleculeA.tsx
│ │ ├─useMoleculeA.ts
│ │ └─atomA.module.scss
│ ├─MoleculeB//MoleculeBコンポーネントに関連するファイルのみを入れるフォルダ
│ │ ├─MoleculeB.tsx
│ │ ├─useMoleculeB.ts
│ │ └─atomB.module.scss
│ └─MoleculeC//MoleculeCコンポーネントに関連するファイルのみを入れるフォルダ
│ │ ├─MoleculeC.tsx
│ │ ├─useMoleculeC.ts
│ │ └─moleculeC.module.scss
│
├─organisms
│ ├─OrganismA//OrganismAコンポーネントに関連するファイルのみを入れるフォルダ
│ │ ├─OrganismA.tsx
│ │ ├─useOrganismA.ts
│ │ └─organismA.module.scss
│ ├─OrganismB//OrganismBコンポーネントに関連するファイルのみを入れるフォルダ
│ │ ├─OrganismB.tsx
│ │ ├─useOrganismB.ts
│ │ └─organismB.module.scss
│ └─OrganismC//OrganismCコンポーネントに関連するファイルのみを入れるフォルダ
│ │ ├─OrganismC.tsx
│ │ ├─useOrganismC.ts
│ │ └─organismC.module.scss
それぞれのカスタムフックとcss-moduleは同じフォルダ内のコンポーネントからしか使用されないので、カスタムフックとcss-moduleは以下のように名称も共通にするのも良いのでは。
src
│
├─atoms
│ ├─AtomA
│ │ ├─AtomA.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
│ ├─AtomB
│ │ ├─AtomB.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
│ └─AtomC
│ │ ├─AtomC.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
│
├─molecules
│ ├─MoleculeA
│ │ ├─MoleculeA.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
│ ├─MoleculeB
│ │ ├─MoleculeB.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
│ └─MoleculeC
│ │ ├─MoleculeC.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
│
├─organisms
│ ├─OrganismA
│ │ ├─OrganismA.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
│ ├─OrganismB
│ │ ├─OrganismB.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
│ └─OrganismC
│ │ ├─OrganismC.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
共に勉強する友達が新しくプロジェクトを作成したのでこのフォルダ構成を紹介すると気に入ってくれて試してくれることに、、、(1月前くらいかなぁ)
そして先日、冬休みが明け学校に向かう際、沢山の問題に気付く。
良くない点
-
そもそも、atomとmoleculeはロジックを持たないことが多いため、カスタムフックを使用しない。
-
できるだけatomやmoleculeには状態やロジックを持たせないように設計するため、カスタムフックを使用しない。
-
小さく独立性の高いコンポーネントは、スタイルも親に決めてもらうように設計するため、css-moduleを使用しないことが多い。
-
organismsもロジックやスタイルがないこともあるため、カスタムフックやcss-moduleを使用しないことがある。
-ロジックが多いコンポーネントはカスタムフックが複数になることがあるため、カスタムフックのtsファイル名を「hook」にするなどで共通化は厳しい。依存したstateがなにか、なにをするhookなのかを命名したほうがよさそう。
以上の問題により、実際はそれぞれのコンポーネントのフォルダ内には、
- コンポーネントとカスタムフックとcss-module
- コンポーネントとカスタムフック
- コンポーネントとcss-module
- コンポーネントのみのためフォルダから出すorコンポーネントのみ
- カスタムフックが複数あるフォルダと存在しないフォルダ
とフォルダ内ファイル数が毎回変わり少し煩雑になり、見にくいし扱いずらい気がする。↓
Aパターン(フォルダ内がコンポーネントのみの場合も変わらずフォルダ内に格納)
src
│
├─atoms
│ ├─AtomA
│ │ └─AtomA.tsx
│ ├─AtomB
│ │ ├─AtomB.tsx
│ │ └─style.module.scss
│ └─AtomC
│ │ └─AtomC.tsx
│
├─molecules
│ ├─MoleculeA
│ │ ├─MoleculeA.tsx
│ ├─MoleculeB
│ │ └─MoleculeB.tsx
│ └─MoleculeC
│ │ ├─MoleculeC.tsx
│ │ └─style.module.scss
│
├─organisms
│ ├─OrganismA
│ │ ├─OrganismA.tsx
│ │ └─style.module.scss
│ ├─OrganismB
│ │ ├─OrganismB.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
│ └─OrganismC
│ │ ├─OrganismC.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
Bパターン(フォルダ内がコンポーネントのみの時、コンポーネントを外に出した場合)
src
│
├─atoms
│ ├─AtomA
│ │ └─AtomA.tsx
│ ├─AtomB
│ │ ├─AtomB.tsx
│ │ └─style.module.scss
│ └─AtomC.tsx
│
├─molecules
│ ├─MoleculeA
│ │ ├─MoleculeA.tsx
│ ├─MoleculeB.tsx
│ └─MoleculeC
│ │ ├─MoleculeC.tsx
│ │ └─style.module.scss
│
├─organisms
│ ├─OrganismA
│ │ ├─OrganismA.tsx
│ │ └─style.module.scss
│ ├─OrganismB
│ │ ├─OrganismB.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
│ └─OrganismC
│ │ ├─OrganismC.tsx
│ │ ├─hook.ts
│ │ └─style.module.scss
個人的にはAパターンの方が、「コンポーネントのためのフォルダを作成する」といったルール化がされているので、import文を書く際に分かりやすいのでこちらを推す。
また、例えばatomでもInput要素を扱うものなどでフォルダ分けしたい時もありその場合さらに一段と階層が深くなる。このフォルダ構成を貫くのが難しい。柔軟性が無い。
感想
vscodeでこの構成を見たとき、フォルダまみれでなんか引く...。問題点を友達に報告した際、このままでは理想と違った見た目や使用感になることを嫌がり今回はいつも通りのフォルダ構成に途中変更しそうな様子。
実際に開発を進めていてメリットを感じなかったらしい。また、コンポーネント数10数個ですでにフォルダが多くて扱いにくく混乱していたらしい。
問題について、なぜ早く気付かなかったんだと言われてその通りだと思った。でも実際にこの構成を実践しているあなたこそなぜ気づかなかったんだと言おうと思ったが、頭を抱えていたので言えなかった。なんかごめん。
そもそも一対一の関係のカスタムフックとcss-moduleの命名は、
カスタムフック名:use{コンポーネント名}
css-module名:{先頭を小文字にしたコンポーネント}.module.scss
としていれるだけで十分わかりやすいので今のままで良かったのかなと思う。
ただ、自分は開発をする際に、css-moduleとカスタムフックが、コンポーネントに対して1体1になりがちなので、着想はよかったと思う。現状に不満ありますし、現状よりもっと良い方法ありそうと考えているのでまた次回あります...