2021-10-11 12:57:54 +00:00
---
2022-10-06 09:15:30 +00:00
title: "plugins"
2023-10-18 10:59:43 +00:00
description: "Nuxt has a plugins system to use Vue plugins and more at the creation of your Vue application."
2022-11-21 15:51:39 +00:00
head.title: "plugins/"
2023-10-18 10:59:43 +00:00
navigation.icon: i-ph-folder-duotone
2021-10-11 12:57:54 +00:00
---
2023-10-18 10:59:43 +00:00
Nuxt automatically reads the files in the `plugins/` directory and loads them at the creation of the Vue application.
2021-06-08 21:44:30 +00:00
2023-10-18 10:59:43 +00:00
::callout{color="blue" icon="i-ph-info-duotone"}
All plugins inside are auto-registered, you don't need not add them to your `nuxt.config` separately.
2021-10-14 17:31:30 +00:00
::
2023-10-18 10:59:43 +00:00
::callout{color="yellow" icon="i-ph-lightbulb-duotone"}
You can use `.server` or `.client` suffix in the file name to load a plugin only on the server or client side.
::
2022-01-18 16:43:41 +00:00
2023-10-18 10:59:43 +00:00
## Registered Plugins
2022-01-18 16:43:41 +00:00
2023-10-18 10:59:43 +00:00
Only files at the top level of the directory (or index files within any subdirectories) will be auto-registered as plugins.
2022-01-18 16:43:41 +00:00
2023-10-18 10:59:43 +00:00
```bash [Directory sturcture]
-| plugins/
---| foo.ts // scanned
---| bar/
-----| baz.ts // not scanned
-----| foz.vue // not scanned
-----| index.ts // currently scanned but deprecated
2022-01-18 16:43:41 +00:00
```
2023-10-18 10:59:43 +00:00
Only `foo.ts` and `bar/index.ts` would be registered.
To add plugins in subdirectories, you can use the [`plugins` ](/docs/api/nuxt-config#plugins-1 ) option in `nuxt.config.ts` :
```ts [nuxt.config.ts]
export default defineNuxtConfig({
plugins: [
'~/plugins/bar/baz',
'~/plugins/bar/foz'
]
})
```
2022-01-18 16:43:41 +00:00
2022-08-13 07:27:04 +00:00
## Creating Plugins
2021-10-14 17:31:30 +00:00
2022-11-16 10:04:28 +00:00
The only argument passed to a plugin is [`nuxtApp` ](/docs/api/composables/use-nuxt-app ).
2021-10-14 17:31:30 +00:00
2023-10-18 10:59:43 +00:00
```ts [plugins/hello.ts]
2021-10-14 17:31:30 +00:00
export default defineNuxtPlugin(nuxtApp => {
// Doing something with nuxtApp
})
```
2023-04-11 11:58:43 +00:00
### Object Syntax Plugins
It is also possible to define a plugin using an object syntax, for more advanced use cases. For example:
2023-10-18 10:59:43 +00:00
```ts [plugins/hello.ts]
2023-04-11 11:58:43 +00:00
export default defineNuxtPlugin({
name: 'my-plugin',
enforce: 'pre', // or 'post'
async setup (nuxtApp) {
// this is the equivalent of a normal functional plugin
},
hooks: {
2023-10-18 10:59:43 +00:00
// You can directly register Nuxt app runtime hooks here
2023-04-11 11:58:43 +00:00
'app:created'() {
const nuxtApp = useNuxtApp()
2023-10-31 12:56:47 +00:00
// do something in the hook
2023-04-11 11:58:43 +00:00
}
2023-10-18 10:59:43 +00:00
},
env: {
// Set this value to `false` if you don't want the plugin to run when rendering server-only or island components.
islands: true
2023-04-11 11:58:43 +00:00
}
})
```
2023-10-18 10:59:43 +00:00
::callout
If you are using the object-syntax, the properties may be statically analyzed in future to produce a more optimized build. So you should not define them at runtime. :br
For example, setting `enforce: process.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins.
2023-04-11 11:58:43 +00:00
::
2023-10-18 10:59:43 +00:00
## Registration Order
2022-10-11 12:14:18 +00:00
2023-05-18 13:09:31 +00:00
You can control the order in which plugins are registered by prefixing with 'alphabetical' numbering to the file names.
2022-10-11 12:14:18 +00:00
2023-10-18 10:59:43 +00:00
```bash [Directory structure]
2022-10-11 12:14:18 +00:00
plugins/
2023-05-18 13:09:31 +00:00
| - 01.myPlugin.ts
| - 02.myOtherPlugin.ts
2022-10-11 12:14:18 +00:00
```
2023-05-18 13:09:31 +00:00
In this example, `02.myOtherPlugin.ts` will be able to access anything that was injected by `01.myPlugin.ts` .
2022-10-11 12:14:18 +00:00
This is useful in situations where you have a plugin that depends on another plugin.
2023-10-18 10:59:43 +00:00
::callout{color="blue" icon="i-ph-info-duotone"}
2023-05-18 13:09:31 +00:00
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` .
::
2023-10-18 10:59:43 +00:00
## Loading Strategy
2023-06-18 16:43:39 +00:00
2023-12-14 17:11:08 +00:00
### Parallel Plugins
2023-06-18 16:43:39 +00:00
By default, Nuxt loads plugins sequentially. You can define a plugin as `parallel` so Nuxt won't wait the end of the plugin's execution before loading the next plugin.
2023-12-14 17:11:08 +00:00
```ts [plugins/my-plugin.ts]
2023-06-18 16:43:39 +00:00
export default defineNuxtPlugin({
name: 'my-plugin',
parallel: true,
async setup (nuxtApp) {
2023-07-24 19:46:50 +00:00
// the next plugin will be executed immediately
2023-06-18 16:43:39 +00:00
}
})
```
2023-12-14 17:11:08 +00:00
### Plugins With Dependencies
If a plugin needs to await a parallel plugin before it runs, you can add the plugin's name to the `dependsOn` array.
```ts [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
}
})
```
2023-10-18 10:59:43 +00:00
## Using Composables
2022-08-22 14:09:12 +00:00
2023-10-18 10:59:43 +00:00
You can use [composables ](/docs/guide/directory-structure/composables ) as well as [utils ](/docs/guide/directory-structure/utils ) within Nuxt plugins:
2022-08-22 14:09:12 +00:00
2023-10-18 10:59:43 +00:00
```ts [plugins/hello.ts]
export default defineNuxtPlugin((nuxtApp) => {
2022-08-22 14:09:12 +00:00
const foo = useFoo()
})
```
However, keep in mind there are some limitations and differences:
2023-10-18 10:59:43 +00:00
::callout
**If a composable depends on another plugin registered later, it might not work.** :br
2022-08-22 14:09:12 +00:00
2023-10-18 10:59:43 +00:00
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.
::
2022-08-22 14:09:12 +00:00
2023-10-18 10:59:43 +00:00
::callout
**If a composable depends on the Vue.js lifecycle, it won't work.** :br
2022-08-22 14:09:12 +00:00
2023-10-18 10:59:43 +00:00
Normally, Vue.js composables are bound to the current component instance while plugins are only bound to [`nuxtApp` ](/docs/api/composables/use-nuxt-app ) instance.
::
2022-08-22 14:09:12 +00:00
2023-10-18 10:59:43 +00:00
## Providing Helpers
2021-10-14 17:31:30 +00:00
2023-10-18 10:59:43 +00:00
If you would like to provide a helper on the [`NuxtApp` ](/docs/api/composables/use-nuxt-app ) instance, return it from the plugin under a `provide` key.
2021-10-14 17:31:30 +00:00
2024-01-02 22:02:42 +00:00
::code-group
2023-10-18 10:59:43 +00:00
```ts [plugins/hello.ts]
2021-11-18 13:11:34 +00:00
export default defineNuxtPlugin(() => {
return {
provide: {
2022-06-10 14:28:17 +00:00
hello: (msg: string) => `Hello ${msg}!`
2021-11-18 13:11:34 +00:00
}
}
2021-10-14 17:31:30 +00:00
})
2021-11-18 13:11:34 +00:00
```
2024-01-02 22:02:42 +00:00
```ts [plugins/hello-object-syntax.ts]
export default defineNuxtPlugin({
name: 'hello',
setup () {
return {
provide: {
hello: (msg: string) => `Hello ${msg}!`
}
}
}
})
```
::
2021-11-18 13:11:34 +00:00
2023-10-18 10:59:43 +00:00
You can then use the helper in your components:
2021-11-18 13:11:34 +00:00
2023-10-18 10:59:43 +00:00
```vue [components/Hello.vue]
2023-07-18 10:31:45 +00:00
< script setup lang = "ts" >
// alternatively, you can also use it here
const { $hello } = useNuxtApp()
< / script >
2021-11-18 13:11:34 +00:00
< template >
< div >
2022-06-10 14:28:17 +00:00
{{ $hello('world') }}
2021-11-18 13:11:34 +00:00
< / div >
< / template >
```
2023-10-18 10:59:43 +00:00
::callout{color="amber" icon="i-ph-warning-duotone"}
Note that we highly recommend using [`composables` ](/docs/guide/directory-structure/composables ) instead of providing helpers to avoid polluting the global namespace and keep your main bundle entry small.
::
2024-01-05 07:52:49 +00:00
::callout{color="amber" icon="i-ph-warning-duotone"}
**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.html#caveat-when-unwrapping-in-templates ).
::
2022-08-13 07:27:04 +00:00
## Typing Plugins
2021-10-14 17:31:30 +00:00
2021-11-18 13:11:34 +00:00
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.
2023-10-18 10:59:43 +00:00
::callout
If you need to use a provided helper _within_ another plugin, you can call [`useNuxtApp()` ](/docs/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.
2021-11-18 13:11:34 +00:00
::
For advanced use-cases, you can declare the type of injected properties like this:
```ts [index.d.ts]
2021-10-14 17:31:30 +00:00
declare module '#app' {
interface NuxtApp {
$hello (msg: string): string
}
}
2021-11-18 13:11:34 +00:00
2023-01-25 15:59:02 +00:00
declare module 'vue' {
2021-11-18 13:11:34 +00:00
interface ComponentCustomProperties {
$hello (msg: string): string
}
}
2023-10-18 10:59:43 +00:00
export {}
2021-10-14 17:31:30 +00:00
```
2021-10-20 13:33:33 +00:00
2023-10-18 10:59:43 +00:00
::callout
2023-04-04 13:23:13 +00:00
If you are using WebStorm, you may need to augment `@vue/runtime-core` until [this issue ](https://youtrack.jetbrains.com/issue/WEB-59818/VUE-TypeScript-WS-PS-does-not-correctly-display-type-of-globally-injected-properties ) is resolved.
2023-03-19 23:22:55 +00:00
::
2022-08-13 07:27:04 +00:00
## Vue Plugins
2021-10-20 13:33:33 +00:00
2021-11-21 12:31:44 +00:00
If you want to use Vue plugins, like [vue-gtag ](https://github.com/MatteoGabriele/vue-gtag ) to add Google Analytics tags, you can use a Nuxt plugin to do so.
2021-10-20 13:33:33 +00:00
2023-10-18 10:59:43 +00:00
First, install the Vue plugin dependency:
2021-10-20 13:33:33 +00:00
2023-10-18 10:59:43 +00:00
::code-group
```bash [yarn]
2021-10-21 09:58:07 +00:00
yarn add --dev vue-gtag-next
2021-10-20 13:33:33 +00:00
```
2023-10-18 10:59:43 +00:00
```bash [npm]
npm install --save-dev vue-gtag-next
```
```bash [pnpm]
pnpm add -D vue-gtag-next
```
```bash [bun]
bun add -D vue-gtag-next
```
::
2021-10-20 13:33:33 +00:00
2023-10-18 10:59:43 +00:00
Then create a plugin file:
2021-10-20 13:33:33 +00:00
2023-10-18 10:59:43 +00:00
```ts [plugins/vue-gtag.client.ts]
2023-01-26 06:48:37 +00:00
import VueGtag, { trackRouter } from 'vue-gtag-next'
2021-10-20 13:33:33 +00:00
export default defineNuxtPlugin((nuxtApp) => {
2021-10-22 10:11:37 +00:00
nuxtApp.vueApp.use(VueGtag, {
2021-10-21 09:58:07 +00:00
property: {
2021-11-11 13:58:08 +00:00
id: 'GA_MEASUREMENT_ID'
2021-10-21 09:58:07 +00:00
}
2021-11-11 13:58:08 +00:00
})
2023-01-26 06:48:37 +00:00
trackRouter(useRouter())
2021-11-11 13:58:08 +00:00
})
2021-10-20 13:33:33 +00:00
```
2022-04-09 09:25:13 +00:00
2022-08-13 07:27:04 +00:00
## Vue Directives
2022-07-06 19:10:29 +00:00
2023-10-18 10:59:43 +00:00
Similarly, you can register a custom Vue directive in a plugin.
2022-07-06 19:10:29 +00:00
2023-10-18 10:59:43 +00:00
```ts [plugins/my-directive.ts]
2022-07-06 19:10:29 +00:00
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.directive('focus', {
mounted (el) {
el.focus()
},
getSSRProps (binding, vnode) {
// you can provide SSR-specific props here
return {}
}
})
})
```
2023-10-18 10:59:43 +00:00
::callout{color="amber" icon="i-ph-warning-duotone"}
2023-08-14 21:28:55 +00:00
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` .
::
2023-10-18 10:59:43 +00:00
:read-more{icon="i-simple-icons-vuedotjs" title="Custom Directives on Vue Docs" to="https://vuejs.org/guide/reusability/custom-directives.html" target="_blank"}