FURYU Tech Blog - フリュー株式会社

フリュー株式会社の開発者が技術情報を発信するブログです。

Next.js(App Router)リポジトリのディレクトリ構成を見直した話

こんにちは。
ピクトリンク開発部 サイトチーム に所属しています松本です🐹

ピクトリンクのフロントエンド開発を主に担当しています。
今回はフロントエンドの改善活動に関する記事を書きました✍️

 

 

はじめに🗣️

運用中のNext.js(App Router)のリポジトリにおいて、ふとしたときに「ちょっとファイル探しにくすぎんか」と感じることがありました。

目的のファイルがどこにあるのか直感的に分からず検索頼みになることが多い状態になっていたし、開発が進む・メンバが増えるにつれて、どんどん苦しくなりそう&リファクタも大変になる!
ということで、チーム内のフロントエンドメンバと協力してディレクトリ構成について改善を実施することにしました。

 

解消したい課題📝
# 以前の構成
src/
 ├─ app/
 │   ├─ aルーティング/   # ルーティングに関連する特別ファイル
 │   ├─ api/             # ディレクトリ構造ベースのapi定義
 │   ├─ bルーティング/
 │   └─ components/
 │       ├─ シナリオ1/   # シナリオベースで分類されたコンポーネント
 │       ├─ シナリオ2/
 │       ├─ シナリオ3/
 │       ├─ Button.tsx   # シナリオに分類されないコンポーネント
 │       ├─ Form.tsx 
 │       └─ Tooltip.tsx
 │   ├─ cルーティング/
 │   ├─ dルーティング/
 │   ├─ server/          # apiやtrpcなど
 │   ├─ store/           # 状態管理
 │   ├─ styles/          # css
 │   ├─ types/           # 型定義
 │   └─ utils/           # 汎用関数
 ├─ stories/              # Storybook
 ├─ test/                 # E2E以外のテスト
 └─ その他のディレクトリ...
  • componentsディレクトリについて
    • シナリオベースや機能ベースでの設計思想が一部で使われているが、全体としてディレクトリ構成が曖昧
    • コンポーネントの粒度や用途が統一されておらず、再利用性や可読性が低下している
    • 再利用できないものが配置されている・誤配置されたファイルが放置されている
  • リポジトリ全体のディレクトリ構成について
    • appディレクトリ配下に、ルートに関係のないserverやstoreなどのディレクトリが存在し、可読性が低下している

 

リファクタ実施に向けた計画と変更内容💪 

期限を決めて、2ステップに分けてリファクタ作業を実施しました。

  1. componentsディレクトリの整理・変更
    • UIに関するコンポーネントは、atomicデザイン*1の考え方に基づいて分類する
      • 別のリポジトリで採用しており、分割の粒度感や分類がイメージし易かったため、atomicデザインを採用した
      • プロジェクトのボリューム感も踏まえて、atoms, molecules, organisms でざっくり分けることにした
    • cssファイルを格納するstylesディレクトリも同じ構成に変更する
    • デザイナーさんに展開できるよう、作成漏れでStorybookに存在しないコンポーネントを洗い出し、新規作成
  2. 全体のディレクトリ構成を変更
    • appディレクトリ配下には、Routing files*2・再利用できないコンポーネント・APIルート*3関連のファイル以外を置かない!というルールの下、構成を検討
    • チーム内でレビュー&作業

 

変えたぞー!🎊 
# 変更後の構成
src/
 ├─ app/
 │   ├─ aルーティング/    # ルーティングに関連する特別ファイル
 │   ├─ api/              # ディレクトリ構造ベースのapi定義
 │   ├─ bルーティング/
 │   ├─ cルーティング/
 │   └─ dルーティング/
 ├─ components/
 │   └─ ui/
 │       ├─ atoms/      # ロジックなしの最小単位コンポーネント
 │       ├─ molecules/  # ロジックなしの複合コンポーネント
 │       └─ organisms/  # ロジックありのコンポーネント
 ├─ server/              # apiやtrpcなど
 ├─ store/               # 状態管理
 ├─ stories/             # Storybook
 ├─ styles/              # css
 ├─ test/                # E2E以外のテスト
 ├─ types/               # 型定義
 ├─ utils/               # 汎用関数
 └─ その他のディレクトリ...

かなり見やすくなりました!やったー!🎉

 

悩んだところ🤔 〜やっぱりfeatureディレクトリって良いの?〜 

現在、再利用できないUIコンポーネンやhooksなどのロジックに関しては、page.tsxが存在するディレクトリに含めているんですが

# こんな感じ
src/
 └─ app/
     └─ login/
         ├─ page.tsx                   # ルーティングエントリ (/loginルーティング)
         └─ loginでしか使われない.tsx  # login専用のUI部品やロジック

ReactアプリケーションのアーキテクチャガイドであるBulletproof Reactでは、featuresというディレクトリが存在します。

# 多分こんな感じ
src/
 ├─ app/
 │   └─ login/
 │       └─ page.tsx
 └─ features/
     └─ login/
         └─ loginでしか使われない.tsx

loginに関連するhooksや型定義などが一括でまとめられていることにより、ドメインでディレクトリが分けられている状態になります。これによって新規参画メンバのファイル捜索時間短縮、全体構成の認知負荷を抑えることにもつながりそう(な気がする)です。
app/ は「ルーティングとページの入口」、features/ は「機能ごとのまとまり」と整理できるという責務分離の観点でも良いですね。

こっちの方が良いのかな〜...?😕

今回は一旦ディレクトリの移動だけで済ませたかったので採用はしませんでしたが、メンバにヒアリングしつつ検討しても良いのかなと思ったり思わなかったり。

 

余談とまとめ🌱

今回はプロジェクト全体に関わる変更のため、最短でリファクタの実施と反映をやってしまいたかったので、普段ロケーション(京都・渋谷・フルリモート)の異なるメンバも1日渋谷に出社し、オフラインで一気に作業しました。

フロント大会議🎺と称して、FigmaやStorybookに関する改善作業・Code Connect*4導入に向けたデザイナーさんとの連携も進めているので、また記事にできたら良いなと思いました!

*1:WebサイトやアプリケーションのUI(ユーザーインターフェース)デザインを、化学の「原子」のように最小の単位から、段階的に組み合わせて構築していく手法。

*2:Next.js App Router における「ルーティング関連の特別ファイル群」のこと。page.tsxやlayout.tsxなど。

*3:Next.js App Router における 「ディレクトリ構造ベースの API 定義ファイル」 であり、HTTP メソッドごとにエクスポートした関数がそのままエンドポイントとして利用される仕組み。

*4:Figmaのデザインシステムと実際のコードベースを直接連携させ、開発者がデザインシステムで使用されている実際のコードスニペットをFigma上で確認できるようにするツール。