
Un plugin Vue 3 est un objet doté d’une méthode install(app, options), installé avec app.use(). Il enregistre composants et directives, fournit des valeurs par app.provide() et configure l’application. Le code Vue 2 à base de Vue.prototype et Vue.mixin ne fonctionne plus.
Un plugin Vue ajoute des capacités à toute une application : un composant disponible partout, une directive, une valeur injectable, une configuration commune. C’est le mécanisme derrière Vue Router, Pinia et la plupart des bibliothèques de l’écosystème.
Ce qu’est un plugin
Un objet doté d’une méthode install, ou une simple fonction. Vue l’appelle avec l’instance d’application et les options passées à app.use().
export default {
install(app, options) {
// tout se passe ici
}
}En Vue 2, install recevait le constructeur global Vue, et un plugin manipulait Vue.prototype, Vue.mixin ou Vue.component. En Vue 3, il n’y a plus de constructeur global : install reçoit l’instance créée par createApp, et tout passe par elle. Un plugin Vue 2 recopié tel quel échoue avec Cannot set properties of undefined (setting '$api') ou un plantage silencieux.
La table de correspondance :
// Vue 2 // Vue 3
Vue.use(Plugin) app.use(Plugin)
Vue.component('X', X) app.component('X', X)
Vue.directive('x', x) app.directive('x', x)
Vue.mixin({ … }) app.mixin({ … })
Vue.prototype.$api = api app.config.globalProperties.$api = api
app.provide('api', api) // préférableUn plugin complet
Voici un plugin qui journalise le montage des composants, expose ce journal et fournit une directive. Il illustre les quatre points d’accroche à connaître.
export default {
install(app, options = {}) {
const prefixe = options.prefixe ?? '[monitor]'
const journal = []
// 1. propriété globale, atteignable par this dans l’Options API
app.config.globalProperties.$journal = journal
// 2. injection : la voie recommandée avec <script setup>
app.provide('journal', journal)
// 3. directive globale
app.directive('surligne', {
mounted(el, binding) {
el.style.backgroundColor = binding.value ?? '#fef08a'
}
})
// 4. mixin global, exécuté au montage de chaque composant
app.mixin({
mounted() {
journal.push(`${prefixe} ${this.$options.__name ?? 'anonyme'} monté`)
}
})
}
}Installation, avec ou sans options :
import { createApp } from 'vue'
import App from './App.vue'
import monitor from './plugins/monitor.js'
const app = createApp(App)
app.use(monitor, { prefixe: '[gekkode]' })
app.mount('#app')Un plugin installé deux fois n’est appliqué qu’une seule fois : Vue tient le registre des plugins déjà passés par app.use().
provide plutôt que globalProperties
app.config.globalProperties.$journal reproduit l’habitude Vue 2 du this.$quelqueChose. Cela fonctionne, mais this n’existe pas dans <script setup> : la propriété n’est atteignable que depuis le gabarit ou l’Options API. Elle échappe aussi à l’autocomplétion et au typage.
app.provide() est la bonne voie. Le composant récupère la valeur par inject :
<script setup>
import { inject } from 'vue'
const journal = inject('journal')
</script>
<template>
<p>{{ journal.length }} composants montés</p>
</template>Pour éviter les collisions de noms de chaîne, utilisez un Symbol exporté par le plugin :
export const cleJournal = Symbol('journal')
export default {
install(app) {
app.provide(cleJournal, [])
}
}Distribuer des composants
Le cas le plus courant : rendre une bibliothèque de composants disponible sans import.
import GkBouton from '../components/GkBouton.vue'
import GkCarte from '../components/GkCarte.vue'
export default {
install(app, { prefixe = 'Gk' } = {}) {
app.component(`${prefixe}Bouton`, GkBouton)
app.component(`${prefixe}Carte`, GkCarte)
}
}Attention au compromis : un composant enregistré globalement est disponible partout, mais échappe au retrait de code mort. Il finit dans le bundle même si personne ne l’utilise. Réservez l’enregistrement global aux composants réellement omniprésents.
Un plugin peut être une simple fonction
Si l’objet à méthode install vous paraît cérémonieux, une fonction suffit : Vue l’appelle avec les mêmes arguments.
export default function titrePlugin(app, options) {
app.config.globalProperties.$titre = options.titre
}Le paquet publiable
Testez-le d’abord dans un projet Vite neuf. Pour le distribuer sur npm, exportez-le par défaut et laissez la dépendance à Vue en peerDependencies, afin que le projet hôte fournisse sa propre copie :
{
"name": "gekkode-monitor",
"type": "module",
"main": "./dist/index.js",
"exports": { ".": "./dist/index.js" },
"peerDependencies": { "vue": "^3.5.0" }
}Les plugins Vue 2 se terminaient souvent par if (window.Vue) window.Vue.use(Plugin), pour s’installer seuls quand la page chargeait Vue par une balise script. Il n’y a plus de window.Vue global en Vue 3 : ce bloc ne sert plus à rien et doit être retiré.
Le mixin global, en dernier recours
Le plugin d’exemple utilise app.mixin pour observer chaque montage. C’est le bon outil pour un besoin transversal comme la télémétrie, où l’on veut vraiment toucher tous les composants.
Pour tout le reste, préférez un composable : une fonction exportée que les composants intéressés appellent. Un mixin global s’applique partout, y compris là où on ne l’attend pas, et rend l’origine d’un comportement difficile à retrouver.
import { inject } from 'vue'
export function useJournal() {
const journal = inject('journal')
return {
journal,
ajouter: (message) => journal.push(message)
}
}Tester un plugin
Vue Test Utils accepte les plugins dans l’option global, avec leurs options :
import { mount } from '@vue/test-utils'
import monitor from '@/plugins/monitor.js'
mount(MonComposant, {
global: { plugins: [[monitor, { prefixe: '[test]' }]] }
})Sans options, la forme courte suffit : plugins: [monitor].
Pour aller plus loin
Beaucoup de bibliothèques de l’écosystème s’installent ainsi, de VueFire à unhead pour le référencement.
Les plugins prennent tout leur sens une fois les composants et l’injection maîtrisés. Si ces notions sont fraîches, reprenez le tutoriel Vue 3 pour les débutants, en particulier les chapitres sur les composants et les props. Pour un état partagé, Pinia est lui-même un plugin, et sa source est une bonne lecture.
Erreurs fréquentes
install reçoit l’instance d’application, plus le constructeur global. Vue.prototype n’existe plus : utilisez app.provide() ou app.config.globalProperties.this n’existe pas dans <script setup> : la propriété n’est lisible que depuis le gabarit. Préférez provide et inject.if (window.Vue) window.Vue.use(Plugin) n’a plus d’objet à trouver en Vue 3 et doit être retiré.

