0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Composableで十分なケース vs プラグインにすべきケース

0
Posted at

色々とまとめて

以下の投稿の続き的なアレです。
今回は結局、色々と便利機能あるけどどういう基準で使ったらええんや? について、
完全に個人的な見解で書いてみようかと。

使うのは自己責任ですが、参考にしてもらえたら幸いワイワイ

どうも、話がまとまらずにダラダラ書いてしまう、え~すけさんですよ。

Composableで十分?それともプラグイン?

Vue 3ではComposableが強力なため、あらゆるロジックをComposableに入れちゃえみたいなところもありますが、
実務では 「それプラグインにすべきでは?」 というケースも合ったりするのかなと。
以下はそれぞれの使い所と、判断するうえでのザックリフローチャートにしてみました。

個人的な基準

まぁ使い所が使い所なので、当たり前体操並な基準ではありますが。。。

  • Composable → 局所的・再利用ロジック
  • プラグイン → 全体に関わる仕組み・ルール

もう少し踏み込んで書いてみるとこんな感じ

Composableで十分なケース

特徴

  • コンポーネント単位、または一部の画面で使う
  • 初期化が不要 or 軽い
  • 依存関係がシンプル
  • UIロジックに近い

例1:データ取得ロジック

export function useUser(id: string) {
  const user = ref(null)
  const loading = ref(false)

  const fetchUser = async () => {
    loading.value = true
    user.value = await fetch(`/api/users/${id}`).then(r => r.json())
    loading.value = false
  }

  return { user, loading, fetchUser }
}

特定の用途で完結する系のアレ

例2:フォーム状態管理

export function useForm() {
  const values = reactive({})
  const errors = reactive({})

  const validate = () => { /* ... */ }

  return { values, errors, validate }
}

UIに近いロジック

例3:UI振る舞い

  • モーダル制御
  • スクロール制御
  • フォーカス管理

コンポーネント寄りなアレ

プラグインにすべきケース

特徴

  • アプリ全体で使う
  • 初期化・設定が必要
  • 依存注入したい
  • ポリシーやルールを統一したい

例1:APIクライアント

export default {
  install(app, options) {
    const client = createApiClient(options)

    app.provide('api', client)
    app.config.globalProperties.$api = client
  }
}

認証・エラー処理・URL管理を一元化

例2:認証・認可

app.provide('auth', {
  user,
  isAuthenticated,
  hasPermission,
})

全画面で使う状態

例3:グローバルエラーハンドリング

app.config.errorHandler = (err) => {
  // ログ送信・通知
}

アプリ全体の振る舞い

例4:設定・Feature Flag

app.provide('config', {
  isEnabled: (key) => { /* ... */ }
})

環境差分・機能制御

判断フローチャート

1. それは「アプリ全体のルール」か?

  • YES → プラグイン
  • NO → 次へ

2. 初期化や設定が必要か?

  • YES → プラグイン
  • NO → 次へ

3. 複数箇所で使うロジックか?

  • YES → Composable
  • NO → コンポーネント内でOK

よくあるミス

なんでもComposableにする

// API設定まで含めてしまう
useApiClient()
  • インスタンスがバラバラになる
  • 設定が分散する

なんでもプラグインにする

app.use(useUser)
  • スコープが広すぎる
  • テストしづらい
  • 依存が見えない

ハイブリッド構成

実際の現場ではこうなるのかなと

  • プラグイン → 基盤を提供
  • Composable → それを使ってロジックを組む

// plugin
app.provide('api', apiClient)
// composable
export function useUser() {
  const api = inject('api')

  const getUser = (id: string) => {
    return api.get(`/users/${id}`)
  }

  return { getUser }
}

役割が明確に分離されるね

まとめると

  • Composableは「ロジックの再利用」
  • プラグインは「仕組みの共有」
  • グローバルにする理由があるかを常に考える

Composableとプラグインは競合するものでなく、レイヤーが違うだけ かなと考えてます。

  • 下層(インフラ) → プラグイン
  • 上層(ユースケース) → Composable

この構造を意識するだけ。

超シンプルに判断するのであれば

さんざん色々と言ってきましたが、とりあえず最初は大体コレでいいかなと思ってきたわ。

「それ、差し替えたいと思うか?」

  • YES → プラグイン(DIする)
  • NO → Composable

元も子もないw

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?