LoginSignup
44
37

More than 1 year has passed since last update.

個人的にたどり着いたディレクトリ構造

Last updated at Posted at 2023-02-14

はじめに

最近VueやReactを何度か触って得た知見を元に、個人的に良さげなディレクトリ構造を考えたいと思います

2023/02/18 追記
多くの方に見てもらえているようなので全体的にちゃんと書き直しました!

ディレクトリ構造

Next.js 13だと仮定します

src/
├── app
│   ├── globals.css
│   ├── head.tsx
│   ├── layout.tsx
│   └── page.tsx
├── components
│   ├── base
│   │   ├── atoms
│   │   └── molecules
│   ├── feature
│   │   └── hoge
│   │       ├── atoms
│   │       ├── molecules
│   │       ├── hooks
│   │       ├── hoge.constants.ts
│   │       └── hoge.types.ts
│   ├── functional
│   └── page
├── hooks
├── libs
├── pages
│   └── api
├── providers
├── stores
│   └── fuga
│       ├── atoms.ts
│       ├── operations.ts
│       ├── selectors.ts
│       └── types.ts
├── types
└── utils

基本

基本は以下の構成を参考にさせていただいています

命名規則としては、複数形を基本に、componentsの子ディレクトリだけは単数形にしていますが、好みの問題だと思います

app

Next.js 13で追加されたApp Directoryによるディレクトリです。詳細は割愛しますが、layoutが使いやすいのでApp Directoryが使えるなら使いたいと思ってます

components

まずは、こちらの記事をご覧ください

BCD Designは、大規模な開発ではとても有効だと思います。しかし、小規模の開発ならここまで細かく分ける必要がないんじゃないかなと使っていて思ったので、ここではbasefeatureのふたつに分けています

BCD Designにおける迷いにくい粒度や「明名する」という考え方は小規模開発においてもとても有効ですので、積極的に取り入れます

base

BCD Designにおけるbaseに該当します。atomsmoleculesの分け方はBCD Designに準拠します

feature

BCD Designにおけるdomainに該当します。domainは単数形で命名します

BCD Designにおけるcaseが存在しないのは、小規模の開発だと私がcaseをうまく使いこなせなかったからです。例えば、

  • Button (base)
  • AddButton (case)
  • UserAddButton (domain)

と分けても、AddButtonUserAddButtonでしか使われないことが多いです。caseを再利用するのってなかなか難しいんですよね

また、case専属のディレクトリ化することが多かったです

例えば、addの中にAddButtonがあったとして、それ以外にaddなんちゃらを作る機会がないとします。これが専属化です

つまり、addディレクトリはAddButtonを作りたいがために設けられ、そのAddButtonもほとんど再利用されないという遠回り感が生まれてしまうのです。それならばdomainに統合してしまっていいのではないかということでこの分け方を採用しています。commonも同様の理由でdomainに統合しています

色々なディレクトリ構造を見ている方ならお分かりだと思いますが、汎用的な部品(base)と機能ごとに分ける(feature)やり方はfeatureディレクトリを採用しているディレクトリ構造と意図がほぼ一緒です

では、なぜわざわざBCD Designについて持ち出したかというと、BCD Designにおけるatomsmoleculesの分け方や「明名する」という考え方を取り入れたいと考えたからです

atomsとmolecules

Buttonなどの単一的なコンポーネントはatomsCardListなどの複合的なコンポーネントはmoleculesに入れます

atomsmoleculesでは1ファイルにpresenterとcontainerの両方を定義します。

src/components/feature/hoge/atoms/HogeButton.tsx
export type HogeButtonPresenterProps = {
    children: React.ReactNode
}

export const HogeButtonPresenter = ({children}: HogeButtonPresenterProps) => {
    return <button>...</button>
}

export type HogeButtonProps = {
    ...
}

export const HogeButton = (...) => {
    return <HogeButtonPresenter>...</HogeButtonPresenter>
}

presenterは基本的にそのファイル内ぐらいでしか使わないので接尾辞としてPresenterをつけます。しかし、containerは他のところでも頻繁に使われる可能性があり、毎回Containerをつけるのは面倒かつ見栄えが悪いので接尾辞はつけません(慣例的に接尾辞なし===Containerとする)

hooks

hooksにはそのドメインのスコープでしか使用しないhookを入れます。

その他

hoge.constants.tsにはそのドメインの定数を、hoge.types.tsにはそのドメインのスキーマと型定義を入れます。わざわざディレクトリを切る必要はないと思います

functional

詳細は以下の記事をご覧ください

functionalはなくてもいいと思います。とりあえず私はRecoilのRecoilObserver.tsxを置いています

page

featureは機能を軸に分類しますが、pageは画面を軸に分類します。pageで行うのはfeatureを組み合わせることだけです。src/app/page.tsxでは直接featureをimportせず、src/components/pageを介します。ただし、src/app/layout.tsxだけは直接featureをimportするのを許可します

pages

Next.jsのAPI Routesのためのディレクトリです。API Routesを使わないなら必要ありません

hooks

特定の機能にとらわれない汎用的なhookを入れます

providers

特定の機能にとらわれない汎用的なproviderを入れます。

そもそもproviderはあまり使わないようにします。理由は、storeshooksがあるのにわざわざprovidersまで必要になる場面ってなかなかないかなと思ったからです

types

特定の機能にとらわれない汎用的なスキーマや型定義を入れます。

typesの中でさらにどのように分けるかは、まだ洗練しきれていないです。正直types/index.ts一本でいいような気もしてます。限定的な型はfeature/hoge/hoge.types.tsで管理してますし、typesの中でさらに細かく分けるとどの程度の粒度で分ければいいかという問題が生じてしまいます

stores

Recoilなどの状態管理を伴うhookはここに入れます。詳細は以下の記事をご覧ください

が、最近Jotaiもなかなか良いなと感じているので、ここの中身は使用している状態管理ライブラリによると思います

utils

汎用的な関数などを入れます

libs

ライブラリの設定などを入れます

その他気をつけること

TailwindCSS

ReactでTailwindCSSを使う際は以下の記事の内容を参考にします

Storybookやテストファイル

hoge.stories.tsxhoge.spec.tsxは対象コンポーネント(hoge.tsx)と同階層に置きます。わざわざstoriesディレクトリや__tests__ディレクトリを設けないということですね

おわりに

こういうの考えてもどうせ数ヶ月後には変わってるんですよね

BCD Designをもっと上手く使いこなせるようになりたいです

44
37
2

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
44
37