kkeisuke blog

Vue 2 系で作るコンポーネント設計方針

いよいよ Vue 3 がリリースされるということで、Vue 2 系でどのような考えのもとコンポーネントを設計してきたのかをまとめておきたいと思います。

対象

  • CRUD を主とした BtoB アプリケーションを想定
    • 十数項目以上の登録(Form)画面、多機能な一覧画面 etc
    • 管理画面

前提

  • Vue CLI
  • Vuex
  • UIフレームワーク使用
    • View UI (旧 iview) を好んで使用します。Vue 3 はサポートされるのか。。。
  • @vue/composition-api (2020/07/31 時点ではベータ) の導入に踏み切れていません。
    • Vue 3 では Composition API を利用します。
    • Vue 3 がリリースされたら Vue 2 でも @vue/composition-api を導入します。
      • 趣味では導入経験あり
  • チーム開発では service などの独自パッケージ(ディレクトリ)は作りません。
    • プロジェクトルートや src トップには CLI コマンドで作成されたフォルダのみ。
    • コミュニケーションコストや初見殺しを避けるため
    • メンテナーが総入れ替えするたびに負債化していく事が多いため

設計方針

  • Store
    • エンティティ相当 → state
    • 永続化層 → action, mutation
    • ドメインロジック・オブジェクト → getter
      • 業務ロジック
      • アプリケーションロジックは Composition API に移行します。
  • Scoped Slots
    • ドメインサービス
    • アプリケーションサービス
      • 個人開発の場合はサービスパッケージを切ります。
    • Composition API に置き換える予定
      • Vue 2 では @vue/composition-api に変更予定
  • アプリケーションコンポーネント
    • atoms, molecules 相当
    • UIフレームワークにアプリケーション要件を載せたコンポーネント群
    • UIフレームワークの CSS はできるだけ用意されている変数でカスタマイズします。
    • CSS は主にアプリケーションコンポーネントにしか書きません。
  • ドメイン・値コンポーネント
    • atoms, molecules 相当
    • アプリケーションコンポーネントにドメイン要素を載せたもの
  • ユースケース(機能)コンポーネント
    • organisms, template 相当
    • template は省略することが多い
  • コントローラーコンポーネント
    • page 相当
    • チーム開発ではルーティングコンポーネントと分けないことが多い
      • Nuxt のルールに従うため
      • 個人開発だと分けています。
  • ルーティングコンポーネント
    • views 以下
    • 画面遷移はこのコンポーネントでのみ行います。
  • ルートコンポーネント(レイアウトコンポーネント)
    • app, home, login etc

課題

  • 独自パッケージ禁止縛りのため、値オブジェクトを表現するのが難しい
    • 個人開発の場合は値オブジェクトパッケージを切ります。
      • 切れないときは Store の getter、もしくは値コンポーネントに寄せます。できるだけコンポーネントに持ちたくないのですが。。。
  • バリデーション
    • UIフレームワークが内包している場合はそれに従います。
      • 辛いことも多いが、ドキュメントが有るので低コストで運用可能
    • 個人開発の場合はバリデーションパッケージを切ります。
    • できるだけ水際で対処したいが、バックエンド要件にあった層で注入します。
  • 不要なドメインロジックは書きません。サーバーサイド担当者を説得します。
    • フロントエンドの寿命は短い
  • Store でなくても構いませんが、代替が今のところありません。
  • atoms 以下の要素に対する CSS をどう管理するか
    • 基本的には各コンポーネントに閉じて「管理しない」という戦略を取ることが多い
    • 外部CSSにまとめることもありますが、せいぜいクラス2〜3個までにまとめます。(tailwind より更にミニマムなものが欲しい)
  • 似たドメイン問題

終わりに

現時点では上記のような戦略で、できるだけコンポーネント間の依存関係を明確にするように書いています。ユースケース、コントローラーでの仕様変更に対応しやすく、ドメイン・値コンポーネントの追加・削除が安全に行える設計を目指しています。

そろそろ Vue 3 でメモアプリでも作って、現状の戦略をどう変えていくか検討していきたいと思います。