brand logo

ドキュメント

プラグイン

Nuxtには、Vueプラグインやその他をVueアプリケーションの作成時に使用するためのプラグインシステムがあります。

Nuxtは自動的にplugins/ディレクトリ内のファイルを読み込み、Vueアプリケーションの作成時にロードします。

内部のすべてのプラグインは自動登録されるため、nuxt.configに個別に追加する必要はありません。

ファイル名に.serverまたは.clientサフィックスを使用して、サーバーまたはクライアント側でのみプラグインをロードすることができます。

登録されたプラグイン

ディレクトリのトップレベルのファイル(またはサブディレクトリ内のインデックスファイル)のみがプラグインとして自動登録されます。

ディレクトリ構造
-| plugins/
---| foo.ts      // スキャンされる
---| bar/
-----| baz.ts    // スキャンされない
-----| foz.vue   // スキャンされない
-----| index.ts  // 現在スキャンされるが非推奨

foo.tsbar/index.tsのみが登録されます。

サブディレクトリにプラグインを追加するには、nuxt.config.tspluginsオプションを使用できます:

nuxt.config.ts
export default defineNuxtConfig({
  plugins: [
    '~/plugins/bar/baz',
    '~/plugins/bar/foz'
  ]
})

プラグインの作成

プラグインに渡される唯一の引数はnuxtAppです。

plugins/hello.ts
export default defineNuxtPlugin(nuxtApp => {
  // nuxtAppを使用して何かを行う
})

オブジェクト構文プラグイン

より高度なユースケースのために、オブジェクト構文を使用してプラグインを定義することも可能です。例えば:

plugins/hello.ts
export default defineNuxtPlugin({
  name: 'my-plugin',
  enforce: 'pre', // または 'post'
  async setup (nuxtApp) {
    // これは通常の関数型プラグインと同等です
  },
  hooks: {
    // ここで直接Nuxtアプリのランタイムフックを登録できます
    'app:created'() {
      const nuxtApp = useNuxtApp()
      // フック内で何かを行う
    }
  },
  env: {
    // サーバーのみまたはアイランドコンポーネントをレンダリングする際にプラグインを実行したくない場合、この値を`false`に設定します。
    islands: true
  }
})

オブジェクト構文を使用している場合、プロパティは静的に解析され、より最適化されたビルドを生成します。そのため、実行時にそれらを定義すべきではありません。 :br 例えば、enforce: import.meta.server ? 'pre' : 'post'を設定すると、Nuxtがプラグインのために行う将来の最適化を無効にします。 Nuxtはオブジェクト構文を使用する際にフックリスナーを静的にプリロードし、プラグイン登録の順序を気にせずにフックを定義できるようにします。

登録順序

ファイル名に「アルファベット順」の番号を付けることで、プラグインの登録順序を制御できます。

ディレクトリ構造
plugins/
 | - 01.myPlugin.ts
 | - 02.myOtherPlugin.ts

この例では、02.myOtherPlugin.ts01.myPlugin.tsによって注入されたものにアクセスできます。

これは、他のプラグインに依存するプラグインがある場合に便利です。

「アルファベット順」の番号付けに不慣れな場合、ファイル名は数値としてではなく文字列としてソートされることを覚えておいてください。例えば、10.myPlugin.ts2.myOtherPlugin.tsの前に来ます。このため、例では一桁の数字に0を付けています。

ロード戦略

並列プラグイン

デフォルトでは、Nuxtはプラグインを順次ロードします。プラグインをparallelとして定義すると、Nuxtは次のプラグインのロードをそのプラグインの実行終了まで待ちません。

plugins/my-plugin.ts
export default defineNuxtPlugin({
  name: 'my-plugin',
  parallel: true,
  async setup (nuxtApp) {
    // 次のプラグインは即座に実行されます
  }
})

依存関係のあるプラグイン

プラグインが実行される前に他のプラグインを待つ必要がある場合、dependsOn配列にプラグインの名前を追加できます。

plugins/depending-on-my-plugin.ts
export default defineNuxtPlugin({
  name: 'depends-on-my-plugin',
  dependsOn: ['my-plugin'],
  async setup (nuxtApp) {
    // このプラグインは`my-plugin`の実行終了を待ってから実行されます
  }
})

コンポーザブルの使用

Nuxtプラグイン内でコンポーザブルユーティルを使用できます:

plugins/hello.ts
export default defineNuxtPlugin((nuxtApp) => {
  const foo = useFoo()
})

ただし、いくつかの制限と違いがあることを覚えておいてください:

コンポーザブルが後で登録される別のプラグインに依存している場合、動作しない可能性があります。 :br

プラグインは順次呼び出され、他のすべてのものの前に呼び出されます。まだ呼び出されていない別のプラグインに依存するコンポーザブルを使用する可能性があります。

コンポーザブルがVue.jsのライフサイクルに依存している場合、動作しません。 :br

通常、Vue.jsのコンポーザブルは現在のコンポーネントインスタンスにバインドされていますが、プラグインはnuxtAppインスタンスにのみバインドされています。

ヘルパーの提供

NuxtAppインスタンスでヘルパーを提供したい場合、provideキーの下でプラグインから返します。

tips

このセクションは公式ドキュメントの翻訳ではなく、本サイト独自の補足記事です。

Nuxtプラグインの活用ガイド:実務で役立つ使い方と注意点

Nuxtのプラグインシステムは、Vueアプリケーションの機能拡張や共通処理の注入に非常に便利です。しかし、公式ドキュメントだけではわかりにくい実務的なポイントや落とし穴も存在します。本記事では、Nuxtプラグインの基本から応用までを丁寧に解説し、開発現場での課題解決に役立つ情報をお届けします。


1. イントロ:Nuxtプラグインで何が嬉しいのか?

Nuxtプラグインは、アプリケーション全体で使いたい機能やライブラリの初期化、共通処理の注入を簡単に行えます。例えば、APIクライアントのセットアップや認証ロジックの共通化、外部ライブラリの統合などが挙げられます。

これにより、コードの重複を減らし、メンテナンス性を向上させることが可能です。また、サーバーサイドとクライアントサイドでの処理を分けて実行できるため、パフォーマンス最適化やセキュリティ面でも効果的です。


2. まず結論:Nuxtプラグインの要点

  • 自動登録plugins/ディレクトリのトップレベルファイルは自動的に読み込まれる
  • ロード制御:ファイル名の先頭に番号を付けて登録順序を制御可能
  • ロード戦略paralleldependsOnで並列実行や依存関係を設定できる
  • サーバー・クライアント切り分け.server.clientサフィックスで実行環境を限定可能
  • オブジェクト構文:高度な設定やフック登録が可能で、静的解析による最適化も期待できる
  • コンポーザブル利用時の注意:プラグイン内でのコンポーザブル使用は依存関係やVueライフサイクルに注意が必要

3. いつ使うべきか・使わない方がよいケース

使うべきケース

  • アプリ全体で共通して使うライブラリや機能の初期化
  • APIクライアントや認証サービスのセットアップ
  • Vueのグローバルミックスインやディレクティブの登録
  • サーバーサイドとクライアントサイドで異なる処理を分けたい場合

使わない方がよいケース

  • コンポーネント固有のロジックや状態管理(プラグインはグローバルな性質のため)
  • Vueのコンポーネントライフサイクルに依存する処理(プラグインはnuxtAppにバインドされるため)
  • 頻繁に変更されるロジック(プラグインはビルド時に静的解析されるため、動的な変更には不向き)

4. 実務でよくあるユースケースとサンプルコード

ユースケース1:APIクライアントのセットアップ

多くのプロジェクトでAPI通信は共通処理です。プラグインでAxiosなどのクライアントを初期化し、nuxtApp.provideで注入すると、どこからでも簡単に利用できます。

// plugins/api-client.ts
import axios from 'axios'

export default defineNuxtPlugin(nuxtApp => {
  const api = axios.create({
    baseURL: 'https://api.example.com'
  })
  nuxtApp.provide('api', api)
})

利用側は以下のように呼び出せます。

const { $api } = useNuxtApp()
$api.get('/users').then(response => {
  console.log(response.data)
})

ユースケース2:認証ロジックの共通化

認証状態の管理やトークンのセットアップをプラグインで行い、アプリ全体で一貫した認証処理を実現します。

// plugins/auth.client.ts
export default defineNuxtPlugin(nuxtApp => {
  const token = localStorage.getItem('auth_token')
  if (token) {
    // 例: Axiosのヘッダーにトークンをセット
    nuxtApp.$api.defaults.headers.common['Authorization'] = `Bearer ${token}`
  }
})

ユースケース3:外部ライブラリの統合(例:Google Analytics)

クライアントサイドのみで動作するライブラリは.client.tsサフィックスを付けて分離し、SSR時のエラーを防ぎます。

// plugins/ga.client.ts
export default defineNuxtPlugin(() => {
  if (process.client) {
    // Google Analyticsの初期化コード
    window.dataLayer = window.dataLayer || []
    function gtag(){window.dataLayer.push(arguments)}
    gtag('js', new Date())
    gtag('config', 'GA_MEASUREMENT_ID')
  }
})

5. よくある落とし穴・注意点

SSRとCSRの違いによる問題

  • .client.serverサフィックスを適切に使わないと、サーバーでしか動かない処理がクライアントで実行されてエラーになることがあります。
  • 逆にクライアント専用の処理をサーバーで実行しようとすると、Hydrationエラーやパフォーマンス低下の原因になります。

プラグインの登録順序に注意

  • 依存関係のあるプラグインは、ファイル名の番号付けやdependsOnで明示的に順序を制御しないと、未定義の状態で利用されてしまうことがあります。
  • ファイル名のソートは文字列として行われるため、10.plugin.ts2.plugin.tsより前に来る点に注意してください。

コンポーザブルの利用制限

  • プラグイン内でVueのコンポーネントライフサイクルに依存するコンポーザブルを使うと、期待通りに動作しません。
  • また、他のプラグインに依存するコンポーザブルは、依存関係の順序を正しく管理しないと動作しないことがあります。

パフォーマンスへの影響

  • プラグインはアプリ起動時に実行されるため、重い処理を入れると初期表示が遅くなります。
  • 並列ロード(parallel: true)を活用しつつ、必要な処理だけをプラグインにまとめることが重要です。

6. まとめ

Nuxtプラグインは、アプリケーションの共通機能を効率的に管理できる強力な仕組みです。適切な登録順序やロード戦略を理解し、サーバー・クライアントの違いを意識することで、安定かつパフォーマンスの良いアプリケーションを構築できます。実務ではAPIクライアントや認証、外部ライブラリの統合などで特に役立つため、今回紹介したポイントを押さえて活用してみてください。


プラグインの依存関係やロード順序は、複雑なアプリケーションほど重要になります。ファイル名の命名規則やdependsOnオプションを活用し、トラブルを未然に防ぎましょう。

Vueのコンポーネントライフサイクルに依存する処理はプラグインではなく、コンポーネントやComposableで実装するのがベストプラクティスです。