フロントエンド最強ディレクトリ構成株式会社ラクス勤怠開発2課北嶋初音
View Slide
index● 発表経緯● 開発フェーズによる特徴● 利用技術● ディレクトリ構成見直し● まとめ
発表経緯● 楽楽勤怠のリリースから約2年● 開発も運用フェーズへと移行しつつある● ディレクトリ設計の見直しもたびたび必要があった● 設計方針がある程度固まってきたので共有● 経緯や具体的な移行内容をまとめておく
開発フェーズによる特徴初期開発スピード重視● 共通化○ 1箇所直したらで全部直って欲しい● 機能要件が満たせればOK現在品質(保守性)重視● 責務の分割○ デグレを防止したい○ 修正の影響箇所を絞りたい● テストコードも書きたい
利用技術● Vue.js(2系)● Vuex● TypeScript● Axios● Jest● Testing Library● Storybook※今回分かっておけば良い部分のみ記載
ディレクトリ構成見直し:導入src/├── app/│ ├── components/│ │ ├── base/│ │ ├── pages/│ │ └── parts/│ ├── repositories/│ ├── stores/│ └── types/├── stories/└── tests/
ディレクトリ構成見直し:導入src/├── app/│ ├── components/│ │ ├── base/ → 複数画面で利用される 共通コンポーネント(.vue)│ │ ├── pages/ → 各画面のルートとなる 画面コンポーネント(.vue)│ │ └── parts/ → 各画面で利用される 部品コンポーネント(.vue)│ ├── repositories/│ ├── stores/│ └── types/├── stories/└── tests/
ディレクトリ構成見直し:導入src/├── app/│ ├── components/│ │ ├── base/│ │ ├── pages/│ │ └── parts/│ ├── repositories/ → API通信を行う関数をまとめたファイル( .repo.ts)│ ├── stores/│ └── types/├── stories/└── tests/
ディレクトリ構成見直し:導入src/├── app/│ ├── components/│ │ ├── base/│ │ ├── pages/│ │ └── parts/│ ├── repositories/│ ├── stores/ → API通信の結果など状態を保持しておく Vuexファイル(.store.ts)│ └── types/├── stories/└── tests/
ディレクトリ構成見直し:導入src/├── app/│ ├── components/│ │ ├── base/│ │ ├── pages/│ │ └── parts/│ ├── repositories/│ ├── stores/│ └── types/ → TypeScriptの型情報を記載しておくファイル( .type.ts)├── stories/└── tests/
ディレクトリ構成見直し:導入src/├── app/│ ├── components/│ │ ├── base/│ │ ├── pages/│ │ └── parts/│ ├── repositories/│ ├── stores/│ └── types/├── stories/ → storybookによるコンポーネントカタログのファイル( .stories.ts)└── tests/
ディレクトリ構成見直し:導入src/├── app/│ ├── components/│ │ ├── base/│ │ ├── pages/│ │ └── parts/│ ├── repositories/│ ├── stores/│ └── types/├── stories/└── tests/ → Jest, Testing Library によるテストコードのファイル( .spec.ts)
ディレクトリ構成見直し:導入pagepart basestorerepositorylogic test sotireslogic testcomponent test
ディレクトリ構成見直し:問題点①src/├── app/│ ├── components/│ │ ├── base/│ │ ├── pages/│ │ └── parts/ → どの画面で使われてるのか分かりにくい。。│ ├── repositories/│ ├── stores/ → どの画面で状態が変更されるのか追いにくい。。│ └── types/├── stories/└── tests/
ディレクトリ構成見直し:問題点①src/├── app/│ ├── components/│ │ ├── base/│ │ ├── pages/│ │ └── parts/│ ├── repositories/│ ├── stores/│ └── types/├── stories/ → どのコンポーネントに対して実装済みか分かりにくい。。└── tests/ → どのコンポーネントに対して実装済みか分かりにくい。。
ディレクトリ構成見直し:問題点①src/├── app/│ ├── components/│ │ ├── base/│ │ ├── pages/│ │ └── parts/│ ├── repositories/│ ├── stores/│ └── types/├── stories/└── tests/どの画面・どのコンポーネントに所属しているのかが分かれば良さそう↓pageコンポーネント中心に集めてみる
ディレクトリ構成見直し:partsファイルcomponents/├── pages/│ └── pc/│ └── admin/│ └── department-list/│ └── AdminDepartmentListPc.vue└── parts/└── pc/└── admin/└── department-list/└── admin-department-form/└── AdminDepartmentForm.vuecomponents/└── pages/└── pc/└── admin/└── department-list/├── AdminDepartmentListPc.vue└── parts/└── department-form/└── DepartmentForm.vuebefore after
ディレクトリ構成見直し:partsファイルcomponents/├── pages/│ └── pc/│ └── admin/│ └── department-list/│ └── AdminDepartmentListPc.vue└── parts/└── pc/└── admin/└── admin-department-form/└── AdminDepartmentForm.vuecomponents/└── pages/└── pc/└── admin/└── department-list/├── AdminDepartmentListPc.vue└── parts/└── department-form/└── DepartmentForm.vuebefore after● 利用される画面が分かりやすくなった● フォルダ名やファイル名がシンプルになった● 階層を合わせる必要もなくなった
ディレクトリ構成見直し:storeファイルapp/├── components/│ └── pages/│ └── pc/│ └── admin/│ └── department-list/│ └── AdminDepartmentListPc.vue└── stores/└── Department.tscomponents/└── pages/└── pc/└── admin/└── department-list/├── AdminDepartmentListPc.vue└── store/└── AdminDepartmentListPc.store.tsbefore after
ディレクトリ構成見直し:storeファイルapp/├── components/│ └── pages/│ └── pc/│ └── admin/│ └── department-list/│ └── AdminDepartmentListPc.vue└── stores/└── Department.tscomponents/└── pages/└── pc/└── admin/└── department-list/├── AdminDepartmentListPc.vue└── store/└── AdminDepartmentListPc.store.tsbefore after● 更新される画面が分かりやすくなった● グローバルなStoreから画面専用のStoreになったので、他画面の影響を受けなくなった
ディレクトリ構成見直し:typeファイルapp/├── components/│ └── pages/│ └── pc/│ └── admin/│ └── department-list/│ └── AdminDepartmentListPc.vue└── types/└── department.type.tscomponents/└── pages/└── pc/└── admin/└── department-list/├── AdminDepartmentListPc.vue└── AdminDepartmentListPc.type.tsbefore after
ディレクトリ構成見直し:specファイルsrc/├── app/│ └── components/│ └── pages/│ └── pc/│ └── admin/│ └── department-list/│ └── AdminDepartmentListPc.vue└── tests/└── app/〜 省略 〜└── AdminDepartmentListPc.it.spec.tscomponents/└── pages/└── pc/└── admin/└── department-list/├── AdminDepartmentListPc.vue└── AdminDepartmentListPc.it.spec.tsbefore after
ディレクトリ構成見直し:storiessrc/├── app/│ └── components/│ └── pages/│ └── pc/│ └── admin/│ └── department-list/│ └── AdminDepartmentListPc.vue└── stories/└── app/〜 省略 〜└── AdminDepartmentListPc.stories.tscomponents/└── pages/└── pc/└── admin/└── department-list/├── AdminDepartmentListPc.vue└── AdminDepartmentListPc.stories.tsbefore after
ディレクトリ構成見直し:まとめ①components/└── pages/└── pc/└── admin/└── department-list├── AdminDepartmentListPc.vue├── AdminDepartmentListPc.type.ts├── AdminDepartmentListPc.it.spec.ts├── AdminDepartmentListPc.stories.ts├── parts│ └── department-form│ └── DepartmentForm.vue└── store└── AdminDepartmentListPc.store.tsafterpageコンポーネント中心に集めて各ファイルの利用箇所が分かりやすくやった(責務の分離もできた)
ディレクトリ構成見直し:問題点②pagepart basestorerepositorylogic test sotireslogic testcomponent testビジネスロジックが多くなりがちテストが書きにくいビジネスロジックが多くなりがちテストが書きにくい
ディレクトリ構成見直し:問題点②pagepart basestorerepositorylogic test sotireslogic testcomponent testmodulesmodules● ビジネスロジックを抜き出す階層を作成● export/importでテストも書くやすくする
ディレクトリ構成見直し:modulescomponents/└── pages/└── pc/└── admin/└── department-list├── AdminDepartmentListPc.vue├── AdminDepartmentListPc.type.ts├── AdminDepartmentListPc.it.spec.ts├── AdminDepartmentListPc.stories.ts├── parts│ └── department-form│ └── DepartmentForm.vue└── store└── AdminDepartmentListPc.store.tscomponents/└── pages/└── pc/└── admin/└── department-list├── AdminDepartmentListPc.vue├── AdminDepartmentListPc.type.ts├── AdminDepartmentListPc.it.spec.ts├── AdminDepartmentListPc.stories.ts├── AdminDepartmentListPc.modules.ts├── AdminDepartmentListPc.modules.spec.ts├── parts│ └── department-form│ └── DepartmentForm.vue└── store└── AdminDepartmentListPc.store.tsbefore after
ディレクトリ構成見直し:modulescomponents/└── pages/└── pc/└── admin/└── department-list├── AdminDepartmentListPc.vue├── AdminDepartmentListPc.type.ts├── AdminDepartmentListPc.it.spec.ts├── AdminDepartmentListPc.stories.ts├── parts│ └── department-form│ └── DepartmentForm.vue└── store└── AdminDepartmentListPc.store.tscomponents/└── pages/└── pc/└── admin/└── department-list├── AdminDepartmentListPc.vue├── AdminDepartmentListPc.type.ts├── AdminDepartmentListPc.it.spec.ts├── AdminDepartmentListPc.stories.ts├── AdminDepartmentListPc.modules.ts├── AdminDepartmentListPc.modules.spec.ts├── parts│ └── department-form│ └── DepartmentForm.vue└── store└── AdminDepartmentListPc.store.tsbefore after● pageコンポーネントの肥大化を防げた● ロジックを抜き出したおかげでテストも書きやすくなった
ディレクトリ構成見直し:Pros/ConsPros● 各ファイルの影響箇所が分かりやすくなった● ロジック抜き出しによってコンポーネントやStoreの肥大化を防げた● テストも書きやすくなったCons● 共通化が減るので実装工数は増えた● 実装漏れには気をつける必要がある● 画面特有のものにするか、共通のものにするかの判断が難しいものもある● 移行作業を行うには工数がかかる○ デグレチェック○ コンフリクト解消
まとめ● 開発フェーズによって適切な設計は異なる● 楽楽勤怠では品質(保守性)重視での設計見直しを行った● 画面コンポーネント中心の設計にすることで修正の影響範囲が分かりやすくなった● ビジネスロジックの抜き出し層を設けたおかげでテストも書きやすくなった● 全て画面の持ち物にすることは不可能なので共通部分は消せない、使い分けはしていく必要がある
ありがとうございました!