カオスになりがちなReact-Reduxのファイル構成をまとめた話

こんにちは。
春からスタメンでフロントエンドエンジニアをしております、桑原と申します。
初めての投稿となります。
今後のフロントエンド開発の紹介を意識して、今回は入口となるファイル構成に
ついて紹介させていただきます。

前置き

デファクトスタンダードから乖離することに悩み踠き苦しみ、何が正解なのかを
日々模索しながら開発をすることは、フロントエンドエンジニアの宿命とも言えます。
ファイル数が肥大化しやすい React-Redux での開発ならば尚のことです。

私のモットーは 可読性の高いコードはファイル構成から作るべし です。
そしてここにエンジニアのファイル構成3大訓を示します。

ファイル構成3大訓

  1. 可読性の高いファイル構成は開発を効率化する
  2. 可読性の高いファイル構成は肥大化を防ぐ
  3. 可読性の高いファイル構成はバグを減らす

現時点までで導き出した、 React-Redux でのファイル構成のあり方を示そうと思います。

ファイル構成を決める要因

ファイル構成を決める要因としては主に下記の3点になります。
TUNAG を例に出しながら、各項目について説明します。

  • アプリケーションの規模
  • アーキテクチャ
  • 思想・好み → ノウハウ

アプリケーションの規模 x アーキテクチャ

このお題だけでひとつの記事になりそうですが、だいぶ簡略化して書きます。
アプリケーションの規模を決める要素として、下記の3点が要点になります。

  1. ビジネスロジックの複雑性
  2. 技術的な複雑性
  3. ページ数

下記のような例では1~2の実装方法により複雑性が増します。

  • ログイン情報をフロントで保持し、API を利用する度にトークンを利用する
  • フォームの入力情報を storage に保存し、再訪しても内容を表示したい
  • ユーザーのタイプによってページレイアウトの色を変更したい

これらの例ではフロントのビジネスロジックをどのような技術で実装するのかを
検討しますが、 API や Helper 関数、Middleware、 Utilities を追加したりなど、
さまざまな要素が絡み始めます。

TUNAG ではバックエンドの Rails で生成した View に、 React-Redux を埋め込む実装をしているため、1~2の大部分を Rails で解決しています。

3.のページ数は、1ページあたりのパーツ数によって大きく左右します。
TUNAG では1ページだけでもかなりの複雑性を持ち、画像1. の
タイムラインでは40〜50個の Component から作られております。
そして今後の更なる機能追加やリファクタリングにより、より複雑なロジックが
絡んでくるため、それに耐えられるファイル構成を検討する必要がありました。


図1. TUNAGのタイムライン

 

思想・好み → ノウハウ

デファクトスタンダードが必ずしも最適にならない場合も多々あり、プロジェクトによって工夫を凝らします。
しかし思想、好みを議論に加えると、ファイル管理に限らず、
アーキテクチャーも最終的には宗教戦争に発展しかねません。

思想、好み、ではなく、ノウハウと呼べるものとして、良いモノづくりをするための
開発環境を追求することは永久のテーマですね。

ファイル構成

さて、ここから本題に入ります。
下記の4つのポイントが既読性をあげるための要点です。

  1. ページ単位でファイル構成そのものをグループ化する
  2. ボタンやテキストフィールドなど、パーツを Materials と命名して共通化する
  3. 共有して利用するモジュールは1層目に配置する
  4. CSS in Module で実装する CSS をまとめる

 1. ページ単位でファイル構成そのものをグループ化する

コンポーネント同士を組み合わせて作成するデザイン手法の Atomic Design という
概念があります。

この Atomic Design ではパーツを5レベルの
AtomsMoleculesOrganismsTemplatesPages に分類しますが、
パーツのレベルによってファイルの管理方法も明確化すると
大量の ContainerComponent に混乱せずにまとめることができます。

図2.のファイル構成では、Atomic Designの PagesTemplates 概念を取り入れる
ことによって、ページ単位でファイル構成そのものをグループ化しています。


図2. modulesとtemplatesによるファイル構成

Pages

Pagesmodules と定義し、module 単位で React-Redux の構成を管理することによって、ページごとに Flux の流れを独立させます。

Templates

画面上部のヘッダーやサイドバーなどが Template にあたります。


図3. Templateの例

テンプレートに該当する Container がひとつなら modules の中に
含めて良いかと思います。
複数存在するならば、1階層に templates フォルダを作って管理します。

2. ボタンやテキストフィールドなど、パーツを Materials と命名して共通化する

Organism、 Molecules、 Atoms

レベル3以下の要素は同じ階層としてファイル管理しています。
このときに気をつけなくてはならないのは、これらの要素は大きく2分されることです。

  1. modules から共有されるケース
  2. modules の中でのみ利用するケース

1.の場合は、 modules の各ページから参照されるため、1階層の materials に含めます。
2.の場合は、特定の module 内でのみ使用するため、 materials ではなく、 module 内の components に含みます。


図4. 共通パーツを含めたファイル構成

3. 共有して利用するモジュールは1層目に配置する

汎用的に利用する api や config、 middleware、 utilities、 vendor は src 層に配置します。


図5. 共通して利用するモジュールを含めたファイル構成

4. CSS in Module で実装する CSS をまとめる

従来の CSS はスコープの概念がないため、アプリケーションの規模が
大きくなればなるほど管理が困難になります。
CSS in Module はコンポーネント単位で CSS を独立管理することができるため、
この問題を解消することができます。

CSS をコンポーネント単位で実装することによって、さまざまな恩恵がありますが、
それはCSS in Moduleでググってください。
本題である CSS の管理の方法ですが、大きく下記の3通りなのではないかと思います。

  1. 1階層に stylesheets フォルダを作り、 materials modules のすべての ContainerComponent の CSS をここで管理する
  2. 各コンポーネントと同じ階層に配置する
  3. materials で利用する CSS は materials 以下に、各 module で利用するCSSは各 module 以下で管理する

1.のメリットは、1箇所でCSSをまとめて管理できるのでわかりやすいですが、
コンポーネントが多いと雑多になるというデメリットがあります。

また、2.は CSS もコンポーネントと共に管理できるのでわかりやすいですが、
一箇所で管理することができないため、煩わしさがあります。

3.はある程度数カ所でまとめた上で、 materialsmodules
単位で独立性を保つことができるため、私なら 3.を選択します。


図6. CSSを含めたファイル構成

終わりに

今回は React-Redux のファイル構成についてお話ししました。
React-Redux のノウハウはネット上のブログでは見つけにくい情報が多いので、
引き続き発信をしていこうと思います。