☀️

フロントエンドのコード規約を作成してみた(React×TypeScript)

2024/07/12に公開

なぜコーディングガイドラインを作るのか

コーディングガイドラインを作成して運用するメリットは以下です。

コードの可読性の向上
コーディングガイドラインを規定しチーム全員がコーディングガイドラインに基づいて開発することで、コードの統一性が保たれ、コードの可読性が向上し、保守性が高まります。

チーム内でのコミュニケーションの円滑化
コーディングガイドラインが規定されている場合、チーム内でのコードの書き方についてのコミュニケーションが円滑になります。コードレビューなどでコードの書き方に関して議論する際に、コーディングガイドラインをベースにして議論することで、論点の整理や修正方針の合意が容易になります。

プロジェクトの拡張性の向上
コーディングガイドラインを規定することで、コードの再利用性が高まります。また、コーディングガイドラインに基づいて開発することで、新たな機能の追加や既存機能の変更など、プロジェクトの拡張性を向上させることができます。


開発環境

React.js 18.2.0
(NextJS)
zustand 4.5.2
redux
TypeScript 4.9.5
zod
ESLint 7.32
husky
prettier
Jest
styled-component


基本方針

新規プロジェクトでは全て本ガイドラインを準拠すること
レビュー時点で指摘し、適切に修正を行うこと
例外に関しては、別途相談すること
守られていないコードがあった場合、リファクタリングを可能な限り進めること


ディレクトリ構成

Bulletproof-reactアーキテクチャに基づいて、ディレクトリを構成する

なぜフィーチャーで分けるのか

feature/ディレクトリ配下にディレクトリを作成し、画面毎にstoreやコンポーネントを管理する。これによって他画面との依存性を極力排除し、メンテナンスコストを下げる。

グローバルで使用するstoreやcomponentはfeatureと同じ階層に配置する。グローバルで使用するコンポーネントは特に依存性がないように設計する。

typesも同階層に配置し、各画面での二重管理とならないようにする。

src
|
+-- app               # アプリケーション層を含む:
|   |
|   +-- routes        # アプリケーションルート / ページと呼ばれることもあります
    +-- app.tsx       # メインアプリケーションコンポーネント
    +-- app-provider  # グローバルプロバイダーでアプリケーション全体をラップするアプリケーションプロバイダー
+-- assets            # アセットフォルダーには、画像、フォントなどのすべての静的ファイルを含めることができます
|
+-- components        # アプリケーション全体で使用される共有コンポーネント
|
+-- config            # グローバル設定、エクスポートされた環境変数など
|
+-- features          # 機能ベースのモジュール
|
+-- hooks             # アプリケーション全体で使用される共有フック
|
+-- lib               # アプリケーション用に事前構成された再利用可能なライブラリ
|
+-- stores            # グローバル状態ストア
|
+-- test              # テストユーティリティとモック
|
+-- types             # アプリケーション全体で使用される共有タイプ
|
+-- utils             # 共有ユーティリティ関数

featureディレクトリ構成

src/features
└── [awesome-feature]
     ├── api        # 特定の機能に関連するAPIリクエスト宣言とapi hooksを格納します
     │
     ├── assets     # 特定の機能でしか使用しな静的コンテンツを格納します
     │
     ├── components # 特定の機能のコンポーネントを格納します
     │
     ├── hooks      # 特定の機能のhooksを格納します
     │
     ├── stores     # 特定の機能の状態管理を格納します
     │
     ├── types      # 特定の機能の型を格納します
     │
     ├── utils      # 特定の機能の関数を格納します
     │
     └── index.ts   # 特定の機能のエントリーポイント
                    # 指定された機能のパブリックAPIとして機能します
                    # その機能の外部で使用されるすべてのものをエクスポートします

bulletproof-reactを参照


状態管理の手法

前提として、アプリケーションの規模に応じて、使用するライブラリを選定する
React Redux (大規模プロジェクトで推奨)
zustand (小〜中規模プロジェクトで推奨)
Hook API useReducer (小規模、コンポーネント単位)

Reactでは状態管理の他にも非同期処理やパフォーマンスの最適化などの観点でも設計する必要があるので、どんな方法で状態管理を行うにしても、当ガイドラインでは、レイヤーの深すぎるクリーンアーキテクチャを避け、保守性を担保できるようにすることを念頭に置くようにする


クリーンアーキテクチャのデザインパターン

(草案)フィーチャー毎のクリーンアーキテクチャ

フィーチャー毎に機能を分割し、オニオンアーキテクチャと同様に依存関係は「上の層から下の層」のみ許可する
このパターンでは、UseCaseをcontrollersで実質的に呼び出すようにしており、 Repositoryの役割をreducerが担い、storeのデータにアクセスするようにしている。



ESLintとPrettier

コードの書き方や、インデントなど余計な議論ををせず、各個人での差異を無くし、一定の書き方に統一するために導入する
コードのスタイルを整える時間を無くす
リポジトリ作成時に必ず導入する
huskyを使って、修正の保存時とコミット時点でオートフォーマットするように設定する


参考

https://techblog.stanby.co.jp/entry/coding_guidelines
https://github.com/alan2207/bulletproof-react/blob/master/docs/project-structure.md
https://zenn.dev/akfm/articles/7dca8c8543ffe6
https://zenn.dev/pandanoir/articles/6c95391842fc61
https://typescript-jp.gitbook.io/deep-dive/styleguide
https://ics.media/entry/200409/
https://qiita.com/70ki8suda/items/7b720217c9b1b4855e9

Discussion