フロントエンドのディレクトリ構成を変えた 2023
背景
Atomic Design ベースのディレクトリ構成になっていたが、 molecules と ogranisms のルールが定まっておらず、コンポーネントがどっちに入るのかが個々人の感覚になっていた
一部の機能は機能ごとにディレクトリを切っていてルールが曖昧になっていた
テストと実装が別ディレクトリにあって、集約性の観点で見通しが悪かった
一行まとめ
Atomic Design ベースから features (機能ごと)に分ける方向にディレクトリ構成を変更した。
方針 (フィロソフィー)
関心が近いものは近い場所になるべく集約させる
ガチガチに縛るよりはある程度レールを引くのに止める
特に features の中のルールは固められないと判断して決定を遅らせる
ルール化できそうなものをLintエラーで管理する
実はまだやってない。インポートの制約に関するルールを追加する予定
採用したルール
機能単位でディレクトリを切る
テストとストーリーも同じディレクトリに置く
atomic design の関心でディレクトリを切るのは廃止する
フォルダは kebab-case, ファイルは camelCase とする
(ファイルも kebab-case にしたかったけど、変更量が多すぎて断念した)
考える上で参考にしたもの
ReactのBestPractice集的なリポジトリ
Feature の粒度でグループしている
ベースはこのディレクトリ構成にした。
ディレクトリ構成を見ただけでそれがどんなプロジェクトかわかるようにするの良い
Screaming Architecture という呼び方をしてた
kebab-case にする
MacOSだとcase sensitiveがデフォルトじゃないため
相対パスを使わない
移動してもパスが変わらんから良いよね的な感じ
@ をprefixにつけるのはわかりやすいかも
Colocationのエッセンシャルが書いてある記事
Colocation≒関心が近いものを近い場所に集約する
機能を集約するとは、という考え方の参考にした
あとはzennやqiitaなどで他社事例を見た。Featureで分けるのが主流なように感じた。
昨今のColocationの文脈で採用されるようになったという認識。
進め方
ADRに上記のような方針とディレクトリ構成の叩き台を持っていって議論して決定した
元々課題感を擦り合わせたりしていたのでちゃぶ台返されるようなことはなかった
負債返済日に気合いでファイルを変更した
一気に100%完璧にするというよりは方針があっていればいいよね的なノリで進める
マージ
https://gyazo.com/717b95c4759d8e3b18c2b57835856bb2
最終的なディレクトリ構成
大体こんな感じ。基本的にはほぼ bulletproof-react。
code:text
/
|
+-- .storybook # storybookを起動するための設定
|
+-- public # favicon, manifest やアセットなど
|
+-- pages # Next.jsのページディレクトリ
|
+-- src # アプリケーションコードを入れる。後述。
code:text
src
|
+-- __generated__ # 生成されたGraphQLコードが入る
|
+-- __tests__ # テストに関連する設定・utilityなどが入る
|
+-- __stories__ # アプリケーションのストーリーに関するutlityが入る
|
+-- config # 全体共通の設定ファイル
|
+-- design-system # デザインシステムに関するコードが入る
|
+-- domain # 特定機能に関連しないドメインロジックが入る
|
+-- features # 後述. 機能レベルのコードが入る
|
+-- hooks # features全体で使用するhooksが入る
|
+-- utils # features全体で使用するロジックが入る
|
+-- ui # features全体で使用するコンポーネントが入る
|
+-- infra # apollo, firebaseなど各サービスとの通信に関わるロジックが入る
|
+-- types # パッケージなどの型定義
features に機能(アプリ)に関する実装が入る
他は特定機能に関連しない実装が入る
domain は主にモデルに紐づくForm Validationが入る
code:features
src/features/awesome-feature
|
+-- index.tsx # エントリーポイント
|
+-- some-component.tsx # コンポーネント
|
+-- some-component.test.tsx # コンポーネントのテスト
|
+-- some-component.stories.tsx # コンポーネントのストーリー
|
+-- some-feature-logic.ts # 機能に紐づくロジック
|
+-- ...
|
+-- awesome-sub-feature # サブ機能
依存関係のルール
features 以外のディレクトリから features を参照するのは禁止
やらなかったこと
monorepo化。design-system や domain などのパッケージ切り出し