plugins
En esta página
Nuxt automatically reads the files in the app/plugins/ directory and loads them at the creation of the Vue application.
::note
All plugins inside are auto-registered, you don't need to add them to your nuxt.config separately.
::
::note
You can use .server or .client suffix in the file name to load a plugin only on the server or client side.
::
Registered Plugins#
Only files at the top level of the directory (or index files within any subdirectories) will be auto-registered as plugins.
```bash [Directory structure] -| plugins/ ---| foo.ts // scanned ---| bar/ -----| baz.ts // not scanned -----| foz.vue // not scanned -----| index.ts // currently scanned but deprecated
Only `foo.ts` and `bar/index.ts` would be registered.
To add plugins in subdirectories, you can use the [`app/plugins`](/docs/4.x/api/nuxt-config#plugins-1) option in `nuxt.config.ts`:
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
plugins: [
'~/plugins/bar/baz',
'~/plugins/bar/foz',
],
})
Creating Plugins#
The only argument passed to a plugin is nuxtApp.
```ts twoslash [plugins/hello.ts] export default defineNuxtPlugin((nuxtApp) => { // Doing something with nuxtApp })
### Object Syntax Plugins
It is also possible to define a plugin using an object syntax, for more advanced use cases. For example:
```ts twoslash [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,
},
})
:video-accordion{title="Watch a video from Alexander Lichter about the Object Syntax for Nuxt plugins" videoId="2aXZyXB1QGQ"}
::note
If you are using the object-syntax, the properties are statically analyzed to produce a more optimized build. So you should not define them at runtime. :br
For example, setting enforce: import.meta.server ? 'pre' : 'post' would defeat any future optimization Nuxt is able to do for your plugins.
Nuxt does statically pre-load any hook listeners when using object-syntax, allowing you to define hooks without needing to worry about order of plugin registration.
::
Registration Order#
You can control the order in which plugins are registered by prefixing with 'alphabetical' numbering to the file names.
```bash [Directory structure] plugins/ | - 01.myPlugin.ts | - 02.myOtherPlugin.ts
In this example, `02.myOtherPlugin.ts` will be able to access anything that was injected by `01.myPlugin.ts`.
This is useful in situations where you have a plugin that depends on another plugin.
::note
In case you're new to 'alphabetical' numbering, remember that filenames are sorted as strings, not as numeric values. For example, `10.myPlugin.ts` would come before `2.myOtherPlugin.ts`. This is why the example prefixes single digit numbers with `0`.
::
## Loading Strategy
### Parallel Plugins
By default, Nuxt loads plugins sequentially. You can define a plugin as `parallel` so Nuxt won't wait until the end of the plugin's execution before loading the next plugin.
```ts twoslash [plugins/my-plugin.ts]
export default defineNuxtPlugin({
name: 'my-plugin',
parallel: true,
async setup (nuxtApp) {
// the next plugin will be executed immediately
},
})
Plugins With Dependencies#
If a plugin needs to wait for another plugin before it runs, you can add the plugin's name to the dependsOn array.
``ts twoslash [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 ofmy-plugin`'s execution before it runs
},
})
## Using Composables
You can use [composables](/docs/4.x/directory-structure/app/composables) as well as [utils](/docs/4.x/directory-structure/app/utils) within Nuxt plugins:
```ts [app/plugins/hello.ts]
export default defineNuxtPlugin((nuxtApp) => {
const foo = useFoo()
})
However, keep in mind there are some limitations and differences:
::important If a composable depends on another plugin registered later, it might not work. :br
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. ::
::important If a composable depends on the Vue.js lifecycle, it won't work. :br
Normally, Vue.js composables are bound to the current component instance while plugins are only bound to nuxtApp instance.
::
Providing Helpers#
If you would like to provide a helper on the NuxtApp instance, return it from the plugin under a provide key.
::code-group
``ts twoslash [plugins/hello.ts]
export default defineNuxtPlugin(() => {
return {
provide: {
hello: (msg: string) =>Hello ${msg}!`,
},
}
})
```ts twoslash [plugins/hello-object-syntax.ts]
export default defineNuxtPlugin({
name: 'hello',
setup () {
return {
provide: {
hello: (msg: string) => `Hello ${msg}!`,
},
}
},
})
::
You can then use the helper in your components:
```vue [app/components/Hello.vue]
::important
Note that we highly recommend using [`composables`](/docs/4.x/directory-structure/app/composables) instead of providing helpers to avoid polluting the global namespace and keep your main bundle entry small.
::
::warning
**If your plugin provides a `ref` or `computed`, it will not be unwrapped in a component `<template>`.** :br
This is due to how Vue works with refs that aren't top-level to the template. You can read more about it [in the Vue documentation](https://vuejs.org/guide/essentials/reactivity-fundamentals#caveat-when-unwrapping-in-templates).
::
## 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.
::note
If you need to use a provided helper _within_ another plugin, you can call [`useNuxtApp()`](/docs/4.x/api/composables/use-nuxt-app) to get the typed version. But in general, this should be avoided unless you are certain of the plugins' order.
::
For advanced use-cases, you can declare the type of injected properties like this:
```ts [index.d.ts]
declare module '#app' {
interface NuxtApp {
$hello (msg: string): string
}
}
declare module 'vue' {
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.
First, install the Vue plugin dependency:
::code-group{sync="pm"} ```bash [npm] npm install --save-dev vue-gtag-next
```bash [yarn]
yarn add --dev vue-gtag-next
```bash [pnpm] pnpm add -D vue-gtag-next
```bash [bun]
bun add -D vue-gtag-next
```bash [deno] deno add -D npm:vue-gtag-next
::
Then create a plugin file:
```ts [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 Directives#
Similarly, you can register a custom Vue directive in a plugin.
ts twoslash [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 {}
},
})
})
::warning
If you register a Vue directive, you must register it on both client and server side unless you are only using it when rendering one side. If the directive only makes sense from a client side, you can always move it to ~/plugins/my-directive.client.ts and provide a 'stub' directive for the server in ~/plugins/my-directive.server.ts.
::
:read-more{icon="i-simple-icons-vuedotjs" title="Custom Directives on Vue Docs" to="https://vuejs.org/guide/reusability/custom-directives.html" target="_blank"}