概要
みなさんこんにちは。フルスタックエンジニアの高瀬 @takasehiromichi です。
今回は、Reactのディレクトリ構成について再考する機会があったので、記事にしようと思います。
なお、技術スタックについては以下の記事を参照してください。
Reactのディレクトリ構成について
現状は、フロントエンドのsrc配下は以下のような感じになってます。
@interfaces/ (55) api/ (88) components/ (50) context/ (3) pages/ (136) utils/ (22)
これ、ロカオプMEO側だけ書いているんですが、プロダクトもだいぶ成長してきまして、それぞれのディレクトリ内のファイル数がすごいことになってます。 (かっこ内の数字がファイル数です。)
それぞれのmonorepo内のディレクトリが、こんな感じです。
正直、pagesに至っては、ファイル一覧から目的のファイルを見つけ出すことがほぼ困難になっており、エンジニアは文字列検索して目的のファイルに辿り着く始末です。
また、今後機能拡張していくにあたっても、これらのファイル群から目的のファイルを見つけ出して加筆修正していかないといけないため、効率が良い状態ではありませんでした。
なので、Reactのリーアキテクチャ的なところを推し進めようとしています。
今試していること
bulletproof-react を参考に、取り入れられる箇所を取り入れていく形にしています。
featuresで切る
とりあえず、pagesディレクトリとかだと、pagesディレクトリ内のどこに境界づけられたコンテクストがあるかわからないので、featuresディレクトリで機能ごとなどでまとめます。つまり、今はコンテクストがpagesディレクトリ内で散らかっている状態です。
※境界づけられたコンテクスト:DDD用語ですが、ここでは「特定の領域を区切る境界が明示的に示された状態」の意で使用しています。つまり、login機能に関するファイルはloginディレクトリ内に、profile機能に関するファイルはprofileディレクトリ内に設置することで、loginディレクトリを見るとlogin機能に関するファイル群というコンテクストにまとめられた状態にするということです。
features/<機能名>/routes
実際の画面を描画するtsxを格納します。複数行にわたってcomponentなどの要素を直書きしていくのではなく、極力componentsに書き出したものを参照する形でroutesのファイルに記述していきます。スタイルを長く書いたり、条件分岐が複雑で多岐に渡るなどの場合に、積極的にcomponentに切り出せないか考えます。
features/<機能名>/components
routesから参照するcomponentを格納します。基本的に1ファイル1コンポーネントにします。
features/<機能名>/api
api呼び出しに関する処理を格納します。
features/<機能名>/types
型宣言に関するファイルを格納します。
featuresで切るの外側
features外に設置するものは、基本的にアプリケーション全体で使用するようなものを設置します。
components/
アプリケーション全体で使用するような、componentを格納します。
hooks/
アプリケーション全体で使用するような、hookを格納します。
lib/
アプリケーション全体で使用するような、libを格納します。
providers/
アプリケーション全体で使用するような、providerを格納します。
utils/
アプリケーション全体で使用するような、utilityを格納します。
config/
アプリケーション全体で使用するような、環境変数を引き受けるようなファイル群を格納します。
routes/
アプリケーション全体で使用するような、ルーティング関連はここに格納します。
test/
アプリケーション全体で使用するような、テスト関連はここに格納します。
まとめ
プロダクトが成長してくると、どうしても拡張性やメンテナンス性に気をかけないといけません。より一層開発者体験よくプロダクト開発が行えるように、今後も注力していきたいと思います。