Nuxt/docs/content/1.docs/2.guide/2.directory-structure/1.plugins.md

4.6 KiB

navigation.icon title description head.title
IconDirectory plugins Nuxt reads the files in your plugins directory and loads them at the creation of the Vue application. plugins/

Plugins Directory

Nuxt automatically reads the files in your plugins directory and loads them at the creation of the Vue application. You can use .server or .client suffix in the file name to load a plugin only on the server or client side.

::alert{type=warning} All plugins in your plugins/ directory are auto-registered, so you should not add them to your nuxt.config separately. ::

Which Files Are Registered

Only files at the top level of the plugins/ directory (or index files within any subdirectories) will be registered as plugins.

For example:

plugins
 | - myPlugin.ts
 | - myOtherPlugin
 | --- supportingFile.ts
 | --- componentToRegister.vue
 | --- index.ts

Only myPlugin.ts and myOtherPlugin/index.ts would be registered.

Creating Plugins

The only argument passed to a plugin is nuxtApp.

export default defineNuxtPlugin(nuxtApp => {
  // Doing something with nuxtApp
})

Plugin Registration Order

You can control the order in which plugins are registered by prefixing a number to the file names.

For example:

plugins/
 | - 1.myPlugin.ts
 | - 2.myOtherPlugin.ts

In this example, 2.myOtherPlugin.ts will be able to access anything that was injected by 1.myPlugin.ts.

This is useful in situations where you have a plugin that depends on another plugin.

Using Composables Within Plugins

You can use composables within Nuxt plugins:

export default defineNuxtPlugin((NuxtApp) => {
  const foo = useFoo()
})

However, keep in mind there are some limitations and differences:

If a composable depends on another plugin registered later, it might not work.

Reason: Plugins are called in order sequentially and before everything else. You might use a composable that depends on another plugin which has not been called yet.

If a composable depends on the Vue.js lifecycle, it won't work.

Reason: Normally, Vue.js composables are bound to the current component instance while plugins are only bound to nuxtApp instance.

Automatically Providing Helpers

If you would like to provide a helper on the NuxtApp instance, return it from the plugin under a provide key. For example:

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

In another file you can use this:

<template>
  <div>
    {{ $hello('world') }}
  </div>
</template>

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

Typing Plugins

If you return your helpers from the plugin, they will be typed automatically; you'll find them typed for the return of useNuxtApp() and within your templates.

::alert If you need to use a provided helper within another plugin, you can call useNuxtApp() to get the typed version. But in general, this should be avoided unless you are certain of the plugins' order. ::

Advanced

For advanced use-cases, you can declare the type of injected properties like this:

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

declare module '@vue/runtime-core' {
  interface ComponentCustomProperties {
    $hello (msg: string): string
  }
}

export { }

Vue Plugins

If you want to use Vue plugins, like vue-gtag to add Google Analytics tags, you can use a Nuxt plugin to do so.

There is an Open RFC to make this even easier! See nuxt/nuxt#17143

First, install the plugin you want.

yarn add --dev vue-gtag-next

Then create a plugin file plugins/vue-gtag.client.js.

import VueGtag from 'vue-gtag-next'

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

Vue Directives

Similarly, you can register a custom Vue directive in a plugin. For example, in plugins/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 {}
    }
  })
})

:ReadMore{link="https://vuejs.org/guide/reusability/custom-directives.html"}

::LinkExample{link="/docs/examples/app/plugins"} ::