# Plugin Structure: Install Method Requirements ## Rule A Vue plugin must be either an object with an `install()` method, or a function that serves as the install function. The install function receives the app instance and optional user-provided options. ## Why This Matters 1. **API contract**: Vue's `app.use()` expects a specific interface. Incorrect structure causes silent failures or errors. 2. **Options passing**: The install method receives options that users pass to `app.use()`, enabling plugin configuration. 3. **App access**: The install method receives the app instance, providing access to `app.component()`, `app.directive()`, `app.provide()`, etc. ## Plugin Structures ### Object with install method (recommended) ```typescript // plugins/myPlugin.ts import type { App } from 'vue' interface PluginOptions { prefix?: string debug?: boolean } const myPlugin = { install(app: App, options: PluginOptions = {}) { const { prefix = 'my', debug = false } = options if (debug) { console.log('Installing myPlugin with prefix:', prefix) } app.provide('myPlugin', { prefix }) } } export default myPlugin // Usage app.use(myPlugin, { prefix: 'custom', debug: true }) ``` ### Function as install (alternative) ```typescript // plugins/simplePlugin.ts import type { App } from 'vue' function simplePlugin(app: App, options?: { message: string }) { app.config.globalProperties.$greet = () => { return options?.message ?? 'Hello!' } } export default simplePlugin // Usage app.use(simplePlugin, { message: 'Welcome!' }) ``` ### Factory function pattern (most flexible) ```typescript // plugins/configuredPlugin.ts import type { App, Plugin } from 'vue' interface I18nOptions { locale: string messages: Record> fallbackLocale?: string } export function createI18n(options: I18nOptions): Plugin { return { install(app: App) { // Options are captured in closure - no need to pass through app.use() const { locale, messages, fallbackLocale = 'en' } = options const translate = (key: string): string => { return messages[locale]?.[key] ?? messages[fallbackLocale]?.[key] ?? key } app.provide('i18n', { translate, locale }) } } } // Usage - options passed to factory, not app.use() const i18n = createI18n({ locale: 'fr', messages: { en: { hello: 'Hello' }, fr: { hello: 'Bonjour' } } }) app.use(i18n) // No second argument needed ``` ## Common Plugin Capabilities ```typescript const fullFeaturedPlugin = { install(app: App, options: PluginOptions) { // 1. Register global components app.component('MyButton', MyButtonComponent) app.component('MyInput', MyInputComponent) // 2. Register global directives app.directive('focus', focusDirective) // 3. Provide injectable values (recommended) app.provide('pluginConfig', options) // 4. Add global properties (use sparingly) app.config.globalProperties.$myHelper = helperFunction // 5. Add global mixins (avoid if possible) app.mixin({ created() { // Runs for every component } }) // 6. Custom error handling app.config.errorHandler = (err, vm, info) => { // Handle errors } } } ``` ## TypeScript: Plugin Type Use the `Plugin` type for proper typing: ```typescript import type { App, Plugin } from 'vue' // With options type parameter interface MyOptions { apiKey: string } const myPlugin: Plugin<[MyOptions]> = { install(app: App, options: MyOptions) { // options is typed as MyOptions } } // Without options const simplePlugin: Plugin = { install(app: App) { // No options expected } } ``` ## Common Mistakes ### Missing install method ```typescript // BAD - This is just an object, not a plugin const notAPlugin = { doSomething() { /* ... */ } } app.use(notAPlugin) // Error or silent failure // GOOD const actualPlugin = { install(app) { app.provide('service', { doSomething() { /* ... */ } }) } } ``` ### Forgetting to use the app parameter ```typescript // BAD - Does nothing const uselessPlugin = { install(app, options) { const service = createService(options) // Forgot to register anything with app! } } // GOOD const usefulPlugin = { install(app, options) { const service = createService(options) app.provide('service', service) // Actually makes it available } } ``` ## References - [Vue.js Plugins Documentation](https://vuejs.org/guide/reusability/plugins.html) - [Vue.js Application API](https://vuejs.org/api/application.html)