Plugin definition structure
A plugin is defined as either an object that exposes an install() method, or simply a function that acts as the install function itself. The install function receives the app instance along with additional options passed to app.use(), if any.
How to install a plugin
Plugins are installed on a Vue app instance using app.use(myPlugin, options). The plugin can receive optional configuration options passed as the second argument to app.use().
Plugin install function signature
The install function receives two parameters: the app instance and an options object containing configuration passed to app.use().
Common plugin use cases
Plugins are useful for: (1) registering global components or custom directives using app.component() and app.directive(); (2) making resources injectable throughout the app by calling app.provide(); (3) adding global instance properties or methods by attaching them to app.config.globalProperties; (4) performing a combination of the above.
Global properties via app.config.globalProperties
Global properties and methods can be added to all components by attaching them to app.config.globalProperties in the plugin's install function. This makes them available globally without explicit registration.
Plugin example: translation function
Example plugin that adds a $translate() method to globalProperties. The method takes a dot-delimited key string, splits it, and reduces through the options object to retrieve the translated value: app.config.globalProperties.$translate = (key) => { return key.split('.').reduce((o, i) => { if (o) return o[i] }, options) }
Using provide/inject with plugins
Plugins can use app.provide() to make resources available to components through injection. This allows components to access plugin configuration using the inject() function in the Composition API or the inject option in the Options API.
Injecting plugin options in Composition API
In the Composition API, plugin options provided via app.provide() are accessed using the inject() function: const i18n = inject('i18n') will retrieve the value provided under the 'i18n' key.
Injecting plugin options in Options API
In the Options API, plugin options provided via app.provide() are accessed using the inject property and accessed in lifecycle hooks like created(): inject: ['i18n'] declares the injection, and this.i18n is used to access the value in created().
Pitfall: excessive global properties
Global properties should be used sparingly, as injecting too many global properties from different plugins throughout an app can quickly become confusing.
Plugin file structure recommendation
It is recommended to create plugins in a separate file and export them to keep the logic contained and separate.
Augmenting ComponentCustomProperties for global plugin properties
To add TypeScript support for globally available properties installed by plugins via app.config.globalProperties, use module augmentation on the ComponentCustomProperties interface. Example: declare module 'vue' { interface ComponentCustomProperties { $http: typeof axios; $translate: (key: string) => string } }
Type augmentation must be placed in a TypeScript module
When augmenting types in Vue, the file must contain at least one top-level import or export (even just 'export {}') to be recognized as a TypeScript module. Without a top-level import/export, the augmentation will overwrite the original types instead of augmenting them.
Type augmentation file placement for Vue types
Type augmentation for Vue can be placed in a .ts file or a project-wide *.d.ts file. Either way, it must be included in tsconfig.json. For library/plugin authors, the file should be specified in the 'types' property in package.json.
Augmenting ComponentCustomOptions for plugin custom component options
To add TypeScript support for custom component options provided by plugins (like vue-router's beforeRouteEnter), augment the ComponentCustomOptions interface. Example: declare module 'vue' { interface ComponentCustomOptions { beforeRouteEnter?(to: Route, from: Route, next: () => void): void } }. Follow the same placement rules as global property augmentations.
Example: Augmenting ComponentCustomProperties for global plugins
import axios from 'axios'
declare module 'vue' {
interface ComponentCustomProperties {
$http: typeof axios
$translate: (key: string) => string
}
}
Example: Correct module augmentation with export statement
// Works correctly - includes export {} to be recognized as a module
export {}
declare module 'vue' {
interface ComponentCustomProperties {
$translate: (key: string) => string
}
}
Example: Augmenting ComponentCustomOptions for vue-router
import { Route } from 'vue-router'
declare module 'vue' {
interface ComponentCustomOptions {
beforeRouteEnter?(to: Route, from: Route, next: () => void): void
}
}