plugins

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

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

すべてのプラグインは自動的に登録されるため、nuxt.config に個別に含める必要はありません。
ファイル名に .server または .client サフィックスを使用すると、プラグインをサーバー側またはクライアント側でのみロードできます。

登録済みプラグイン

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

ディレクトリ構造
-| plugins/
---| foo.ts      // scanned
---| bar/
-----| baz.ts    // not scanned
-----| foz.vue   // not scanned
-----| index.ts  // currently scanned but deprecated

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

サブディレクトリにプラグインを追加するには、nuxt.config.ts 内の app/plugins オプションを使用できます。

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

プラグインの作成

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

plugins/hello.ts
export default defineNuxtPlugin((nuxtApp) => {
  // Doing something with nuxtApp
})

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

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

plugins/hello.ts
export default defineNuxtPlugin({
  name: 'my-plugin',
  enforce: 'pre', // or 'post'
  async setup (nuxtApp) {
    // this is the equivalent of a normal functional plugin
  },
  hooks: {
    // You can directly register Nuxt app runtime hooks here
    'app:created' () {
      const nuxtApp = useNuxtApp()
      // do something in the hook
    },
  },
  env: {
    // Set this value to `false` if you don't want the plugin to run when rendering server-only or island components.
    islands: true,
  },
})
オブジェクト構文を使用する場合、プロパティは静的に分析され、より最適化されたビルドが生成されます。したがって、実行時にプロパティを定義するべきではありません。
例えば、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 の前に来ます。そのため、例では1桁の数字に 0 を付けています。

読み込み戦略

並列プラグイン

デフォルトでは、Nuxt はプラグインを順番に読み込みます。プラグインを parallel として定義すると、Nuxt は次のプラグインを読み込む前にプラグインの実行が終了するまで待機しません。

plugins/my-plugin.ts
export default defineNuxtPlugin({
  name: 'my-plugin',
  parallel: true,
  async setup (nuxtApp) {
    // the next plugin will be executed immediately
  },
})

依存関係を持つプラグイン

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

plugins/depending-on-my-plugin.ts
export default defineNuxtPlugin({
  name: 'depends-on-my-plugin',
  dependsOn: ['my-plugin'],
  async setup (nuxtApp) {
    // this plugin will wait for the end of `my-plugin`'s execution before it runs
  },
})

コンポーザブルの使用

Nuxt プラグイン内では、コンポーザブルユーティリティの両方を使用できます。

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

ただし、いくつかの制限と違いがあることに注意してください。

後で登録される別のプラグインにコンポーザブルが依存している場合、動作しない可能性があります。
プラグインは順番に、そして他のすべてよりも先に呼び出されます。まだ呼び出されていない別のプラグインに依存するコンポーザブルを使用する可能性があります。
コンポーザブルが Vue.js のライフサイクルに依存している場合、動作しません。
通常、Vue.js のコンポーザブルは現在のコンポーネントインスタンスにバインドされますが、プラグインは nuxtApp インスタンスにのみバインドされます。

ヘルパーの提供

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

export default defineNuxtPlugin(() => {
  return {
    provide: {
      hello: (msg: string) => `Hello ${msg}!`,
    },
  }
})

その後、コンポーネントでヘルパーを使用できます

app/components/Hello.vue
<script setup lang="ts">
// alternatively, you can also use it here
const { $hello } = useNuxtApp()
</script>

<template>
  <div>
    {{ $hello('world') }}
  </div>
</template>
グローバル名前空間を汚染しないように、またメインバンドルのエントリを小さく保つために、ヘルパーを提供する代わりにコンポーザブルを使用することを強くお勧めします。
プラグインが ref または computed を提供する場合、コンポーネントの <template> 内ではアンラップされません。
これは、Vue がテンプレートのトップレベルではない ref を扱う方法によるものです。詳細はこちらをご覧ください。Vue のドキュメント.

プラグインの型付け

プラグインからヘルパーを返すと、自動的に型付けされます。それらは useNuxtApp() の戻り値およびテンプレート内で型付けされていることがわかります。

別のプラグインで提供されたヘルパーを使用する必要がある場合、型付けされたバージョンを取得するには useNuxtApp() を呼び出すことができます。しかし、プラグインの順序が確実な場合を除き、一般的には避けるべきです。

高度なユースケースでは、次のように注入されたプロパティの型を宣言できます。

index.d.ts
declare module '#app' {
  interface NuxtApp {
    $hello (msg: string): string
  }
}

declare module 'vue' {
  interface ComponentCustomProperties {
    $hello (msg: string): string
  }
}

export {}
WebStorm を使用している場合、@vue/runtime-core を拡張する必要があるかもしれません。この問題が解決されるまで。

Vue プラグイン

次のような Vue プラグインを使用したい場合vue-gtagGoogle Analytics タグを追加するには、Nuxt プラグインを使用できます。

まず、Vue プラグインの依存関係をインストールします。

npm install --save-dev vue-gtag-next

次にプラグインファイルを作成します

app/plugins/vue-gtag.client.ts
import VueGtag, { trackRouter } from 'vue-gtag-next'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(VueGtag, {
    property: {
      id: 'GA_MEASUREMENT_ID',
    },
  })
  trackRouter(useRouter())
})

Vue ディレクティブ

同様に、プラグインでカスタム Vue ディレクティブを登録できます。

plugins/my-directive.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.directive('focus', {
    mounted (el) {
      el.focus()
    },
    getSSRProps (binding, vnode) {
      // you can provide SSR-specific props here
      return {}
    },
  })
})
Vue ディレクティブを登録する場合、片側のレンダリングでのみ使用する場合を除き、クライアント側とサーバー側の両方で登録する必要があります。ディレクティブがクライアント側でのみ意味をなす場合、常に ~/plugins/my-directive.client.ts に移動し、サーバー側用に ~/plugins/my-directive.server.ts に「スタブ」ディレクティブを提供できます。
詳しくはVue Docs のカスタムディレクティブを参照してください。