Vueプロジェクトの複雑さは、コンポーネント数だけで増えるわけではない。業務ロジックがページ、コンポーネント、storeの間に散らばり始めた時に管理しにくくなる。2026年のVueチームには、どのロジックをComposableに抽出し、どの状態をコンポーネント内に留め、どの機能を業務モジュールとして沉淀させるか——Composition Architectureを意識した設計が必要になる。
Composableは万能抽象ではない
すべてを useXxx に切り出すのはよくある誤りだ。短期的には再利用できているように見えるが、長期的には暗黙の依存、ライフサイクルの混乱、テスト困難を生みやすい。より堅牢なアプローチは、Composableを三つの明確な層に分けることだ:
第一層:基盤 Composable(Infrastructure)
この層はビジネスと無関係な、安定した技術的課題だけを扱う。典型的な例:
useRequest:リクエストのキャンセル、リトライ、キャッシュ、競合状態の処理をカプセル化useDebounce/useThrottle:入力のデバウンスとスロットルuseIntersectionObserver:要素の可視性監視useEventListener:イベントバインディングと自動クリーンアップuseMediaQuery:レスポンシブブレークポイント検出
基盤層の特徴は高再利用、ゼロビジネス結合、一方向依存。業務型やドメインロジックを一切参照せず、異なるプロジェクト間で直接移植できる。
第二層:業務フロー Composable(Domain)
この層は明確なドメインルールを持ち、業務ロジックの構造化表現である。典型的な例:
useProductSearch:商品検索のクエリ、フィルタ、ソート、ページネーションロジックをカプセル化useOrderFlow:注文フローの状態機械をカプセル化(カート→住所→支払い→確認)usePermission:現在のユーザーの権限チェックロジックをカプセル化useFormValidation:特定業務フォームのバリデーションルールをカプセル化
ドメイン層の特徴は明確な業務境界、独立したテスト可能性、依存方向が一方向で基盤層を指すこと。この層のComposableは通常、業務固有の型定義や定数を含む。
第三層:ページ適配 Composable(Adapter)
この層は業務フローを現在のページやコンポーネントが必要とする状態の形に変換する。典型的な例:
useProductListPage:useProductSearch+usePagination+ ルートパラメータを組み合わせるuseDashboardData:複数のデータソースのloading/error/data状態を集約useUserProfile:ユーザー情報、権限、編集状態を組み合わせる
適配層の特徴はライフサイクルが特定ページに紐づき、複数のドメインComposableを組み合わせ、ビュー専用の状態を公開すること。通常、他のページで再利用されることはない。
三層間は一方向依存を保つ:適配層 → ドメイン層 → 基盤層。この制約により、プロジェクト規模が大きくなっても依存方向を追跡しやすい。
状態境界を事前に設計する
Vueのリアクティブシステムは柔軟だが、柔軟だからといってどこでも状態を共有してよいわけではない。2026年のベストプラクティスは、状態を作用域で四つのレベルに分けることだ:
L1:コンポーネント内状態(Component State) フォーム入力、ダイアログ開閉、現在のtab、ローカルloadingなどに適用。ライフサイクルが短く、依存範囲が明確。refまたはreactiveを使用し、外部からアクセスすべきではない。
L2:共有コンポーネント状態(Shared Component State) 親子または兄弟コンポーネント間の状態受け渡しに適用。第一選択はdefineProps + defineEmits、次にprovide/inject。最初からグローバルstoreに頼らない。
L3:モジュールレベル状態(Module State) 一つの業務モジュール内で複数ページが共有する状態に適用。典型的な実装は、モジュールレベルのComposableを作成し、内部でrefを使用、provide/injectまたはモジュールシングルトンで公開する。複数の業務エントリが同じ情報源に依存する場合のみ、このレベルに上げる価値がある。
L4:グローバル状態(Global State) モジュールを跨ぐ共有状態(ユーザー情報、グローバル設定、テーマ設定など)に適用。Pinia storeを使用するが、数を厳密に制御する——健全な中〜大規模プロジェクトでは、グローバルstoreの数は通常5個を超えない。
核心原則:状態はコンポーネント内に留められるなら上げない。モジュール化できるならグローバル化しない。 状態の作用域を上げるたびに、より多くの結合とより複雑なテストを意味する。
副作用管理:effectは万能ではない
VueのwatchとwatchEffectは強力なツールだが、乱用されやすい。2026年の成熟した実践:
- watchはリアクティブ同期に使用:Aが変化したらBを更新(ルートパラメータ変化時にデータを再取得するなど)
- watchEffectはデバッグと単純同期に使用:複雑な業務ロジックを載せるのには不向き
- 業務副作用はComposableのメソッドに配置:明示的な呼び出しは暗黙的なトリガーより追跡とテストが容易
実用的な判断基準:watchのコールバックが10行を超える場合、または非同期操作や条件分岐を含む場合、明示的なComposableメソッドへのリファクタリングを検討すべきだ。
テスト戦略
Composition Architectureの最大の工学的利点は、テスト容易性の大幅な向上だ。推奨テストピラミッド:
- 単体テスト(70%):ドメインComposableの純粋ロジックテスト。コンポーネントコンテキストから切り離されているため、
@vue/test-utilsやComposable関数の直接呼び出しで検証できる。最も投資対効果の高いテスト。 - 統合テスト(20%):複数のComposableを組み合わせた後の動作と、Pinia storeとの相互作用を検証。
- コンポーネントテスト(10%):重要な操作経路のみカバー。すべてのコンポーネントにテストを書く必要はない。
コードレビューでは四つの次元に注目:依存方向が正しいか(一方向)、状態の帰属が合理的か(四層モデル)、副作用の入口が明示的か、Composableの入出力が明確か。
移行戦略:混沌から秩序へ
Vueプロジェクトに混雑したmixin、過剰使用されたstore、散在した業務ロジックが蓄積されている場合、一度にリファクタリングしようとしないこと。より現実的な移行経路:
- まず基盤層を抽出:純粋な技術ツール関数を基盤Composableとして抽出する。これが最もリスクの低いステップ
- 次にドメイン層を整理:業務モジュールを修正するたびに、関連ロジックをドメインComposableにカプセル化
- 最後に適配層を統合:新しいページで適配層パターンを使用し、古いページは段階的に移行
- 各段階でテストを書く:テストはリファクタリングの安全網。テストなしに大規模な抽象化をしないこと
まとめ
Vue 2026の核心的競争力は文法の簡潔さだけではない。複雑な業務を安定し、テスト可能で、進化可能な構成単位に分解できることにある。三層Composableアーキテクチャ(基盤→ドメイン→適配)と四レベル状態モデル(コンポーネント→共有→モジュール→グローバル)は、大規模Vueプロジェクトに明確な治理フレームワークを提供する。鍵は:Composableは業務境界に奉仕するものであり、新しいグローバル道具箱にならないことだ。
