logo

【プロジェクト構成編】React Application Architecture for Production が勉強になりすぎる

2023-06-07
a year ago

開発環境

  • react 18.2.0
  • next 13.4.2

前提

今回の記事はReactのベストプラクティスと呼び声の高いbulletproof-reactで有名なAlan氏が2023年1月に公開した著書「React Application Architecture for Production」の紹介です。

ソースコードは公開されているので、こちらを眺めるだけでも学べることはたくさんあると思いますが、個人的に気になる部分を本記事含めいくつかの記事に分けて紹介します。

※上記で記した開発環境のバージョンは実際に動作確認した際に利用したバージョンです。著者で紹介されているバージョンと異なりますのでご了承ください。

本題

今回はプロジェクト構成について紹介します。

まずは全体の構成を見ていきます。

ほとんどのファイルはsrc配下に置かれることになる為、以下はsrc配下の構成になります。

.
├── __tests__
├── components
├── config
├── features
│   └── users
│       ├── api
│       ├── components
│       └── types
├── layouts
├── lib
├── pages
├── providers
├── stores
├── testing
├── types
└── utils

bulletproof-reactでも提唱されていたfeaturesを採用した構成のNextバージョンになっています。

それぞれは以下の役割の担います。

  • components : アプリケーション全体で使用されるすべての共有コンポーネント
  • config : アプリケーション構成ファイル
  • features : すべての機能ベースのモジュール
  • layouts : ページのさまざまなレイアウト
  • lib : アプリケーションで使用されるさまざまなライブラリの構成
  • pages : アプリケーションのページ
  • providers : すべてのアプリケーションプロバイダー
  • stores : アプリケーションで使用されるすべてのグローバル状態ストア
  • testing : テスト関連のモック、ヘルパー、ユーティリティ、および構成
  • types : アプリケーション全体で使用される基本の TypeScript 型定義
  • utils : すべての共有ユーティリティ関数


以下の2点がとても参考になる点です。

  • 関心ごとに分離されることでソースコードの把握が非常にしやすい
  • ディレクトリ名とそれぞれの役割が明確で理解しやすく、チーム間でのズレも少ない


featuresディレクトリについては細かく見ていきます。

features/users
├── api        # 特定の機能に関連する API リクエスト宣言と API フック
├── components # 特定の機能に限定されたすべてのコンポーネント
├── types      # 特定の機能の型定義
└── index.ts   # アプリケーションの他の部分に対してパブリックにする必要があるもののみをエクスポート

features特定の機能の固有のコードが含まれている必要があります。これにより、他の機能と混在させないように機能単位で管理することができます。

これは、多数のファイルを含むフラットなディレクトリ構造よりも保守がはるかに簡単です。

上記の例ではapi, components, types, index.tsが配置されていますが、特定の機能で利用するものは必要に応じて追加していくことになります。(例、utils, hooksなど)

今回は分かりやすくユーザーに関連する機能を想定して「users」としましたが、アプリケーションによって、「jobs」「groups」のような機能ディレクトリが複数配置されることになります。

特に偉いなと感じる点はindex.tsでエクスポートするファイルを管理している点です。

featuresディレクトリで管理していてるファイルを外部で(他の機能ディレクトリで)利用したくなるシーンは少なからず存在します。

その場合に直接インポートしていくと、一体どのファイルが外部で利用されているのか、依存関係を追いにくくなり、結果的にリファクタリングや機能追加していく際にバグを残してしまう可能性もあります。

その対応策としてもまとめてエクスポートすることは有効です。

また、より安全に管理していくためにESLintにルールを追加することも有効です。

rules: {
    'no-restricted-imports': [
      'error',
      {
        patterns: ['@/features/*/*'],
      },
    ],
      …
}

こちらの設定でindex.tsからエクスポートされた場合のみ利用することを強制できます。

開発を進めていくと構成がごちゃごちゃとしてくることがありますが、とくに意識せずともルールに沿うことができるのは重要なことです。

さいごに

プロジェクトによって構成は柔軟に変わっていくものだと思いますが、一つの指針があると設計しやすくなります。

興味がある方は購入おすすめです → React Application Architecture for Production

参照