What Are Global Properties?
Vue.js global properties provide a powerful mechanism for sharing data, utility functions, and configurations across all components in your application. The app.config.globalProperties object serves as the global registry for shared resources that remain accessible without prop drilling or repeated imports.
This guide explores how to leverage global properties effectively in Vue 3, covering implementation patterns, migration strategies from Vue 2, and modern alternatives like composables. Whether you're building a new Vue 3 application or migrating from Vue 2, understanding global properties helps you architect scalable applications with clean component interfaces and maintainable codebases. For teams building complex Vue.js applications, our /services/web-development/ expertise can help ensure your architecture follows best practices.
The Evolution from Vue 2
In Vue 2, developers commonly used Vue.prototype to add instance properties accessible on all component instances. Vue 3 replaced this pattern with app.config.globalProperties, reflecting the new application instance architecture introduced with the Composition API. This shift aligns with Vue 3's application-centric design, where createApp() returns an application instance that encapsulates all configuration, providing a more predictable and testable approach to managing application-wide resources.
Vue 2 to Vue 3 Comparison
// Vue 2 approach
Vue.prototype.$api = apiClient
Vue.prototype.$formatCurrency = formatCurrency
// Vue 3 approach
const app = createApp(App)
app.config.globalProperties.$api = apiClient
app.config.globalProperties.$formatCurrency = formatCurrency
As documented in the Vue 3 Migration Guide, this change provides clearer separation between application configuration and component options, making it easier to reason about where global resources are defined and how they can be modified or extended.
Setting Up Global Properties
Basic Syntax and Usage
The app.config.globalProperties object accepts key-value pairs where keys become available on all component instances using the this context. According to the Vue.js Application API, these properties are inherited by all component instances, providing a consistent way to access application-wide resources throughout your component hierarchy.
// main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// Add a global utility function
app.config.globalProperties.$formatDate = (date) => {
return new Date(date).toLocaleDateString()
}
// Add a global property
app.config.globalProperties.$appName = 'My Vue Application'
app.mount('#app')
Properties can then be accessed in any component:
// Inside any component
export default {
mounted() {
console.log(this.$appName)
console.log(this.$formatDate(new Date()))
}
}
This pattern eliminates the need to import utilities in every file, reducing boilerplate and keeping components focused on their specific responsibilities.
Global properties work well for sharing configured service objects and utility libraries
API Client Integration
Share configured API clients across all components without individual imports, ensuring consistent request/response handling throughout your application.
Utility Libraries
Expose formatting, validation, and helper functions universally for consistent behavior throughout the app without repetitive module imports.
Third-Party Libraries
Integrate and expose libraries like moment, lodash, or validation libraries globally for convenient access across all components.
TypeScript Support
Extend the ComponentCustomProperties interface to enable type safety for your global properties. This augmentation, as demonstrated in practical implementations on the Vue Examples resource, enables full TypeScript intellisense when accessing global properties in your components, improving developer experience and catching potential errors at compile time.
// types/vue-global.d.ts
import { apiClient } from './services/api'
declare module 'vue' {
interface ComponentCustomProperties {
$api: typeof apiClient
$formatters: {
currency(value: number, currency?: string): string
percentage(value: number): string
}
$appName: string
}
}
This type declaration file should be included in your TypeScript compilation context, typically by placing it in your types directory or including it in your tsconfig.json. With proper TypeScript configuration, your IDE will provide autocomplete suggestions and type checking for all globally registered properties. TypeScript integration is a key practice our /services/web-development/ team emphasizes for maintainable codebases.
Common Use Cases
API Client Integration
One of the most common use cases for global properties is sharing configured API clients, as covered in practical tutorials from the LogRocket Blog. By registering your API client globally, you ensure consistent authentication, error handling, and response formatting across all component interactions.
// services/api.js
import axios from 'axios'
export const apiClient = axios.create({
baseURL: process.env.VUE_APP_API_URL,
timeout: 10000,
headers: { 'Content-Type': 'application/json' }
})
apiClient.interceptors.request.use(config => {
const token = localStorage.getItem('auth_token')
if (token) config.headers.Authorization = `Bearer ${token}`
return config
})
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { apiClient } from './services/api'
const app = createApp(App)
app.config.globalProperties.$api = apiClient
app.mount('#app')
Components can now make API calls without individual imports:
// AnyComponent.vue
export default {
async mounted() {
const response = await this.$api.get('/users')
this.users = response.data
}
}
This approach centralizes your API configuration and ensures all components use the same instance, preventing issues with multiple client configurations and making it easier to implement cross-cutting concerns like authentication tokens or response interceptors.
Migration from Vue 2
Vue.prototype to globalProperties
The migration from Vue 2 to Vue 3 involves moving from Vue.prototype to app.config.globalProperties. As outlined in the Vue 3 Migration Guide, the core pattern remains similar, but the API has been updated to work with the new application instance model. This migration is straightforward for most applications, requiring only changes to where global properties are registered.
// Vue 2
// plugins/api.js
export default {
install(Vue) {
Vue.prototype.$api = apiClient
Vue.prototype.$toast = toast
}
}
// main.js
import Vue from 'vue'
import App from './App.vue'
import apiPlugin from './plugins/api'
Vue.use(apiPlugin)
new Vue({ render: h => h(App) }).$mount('#app')
// Vue 3
// plugins/api.js
export default {
install(app) {
app.config.globalProperties.$api = apiClient
app.config.globalProperties.$toast = toast
}
}
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import apiPlugin from './plugins/api'
const app = createApp(App)
app.use(apiPlugin)
app.mount('#app')
The key change is that plugins now receive the application instance as their first argument, rather than the Vue constructor. This aligns with Vue 3's component API design and provides clearer access to application-level configuration. Our Vue.js migration experts can assist with upgrading legacy applications to Vue 3 following these best practices.
Preserving Plugin Compatibility
Create plugins that work with both Vue 2 and Vue 3 for backward compatibility when maintaining libraries or supporting multiple project versions. This pattern allows gradual migration without breaking existing functionality:
// utils/install-plugin.js
export function createPlugin(plugin) {
return {
install(appOrVue, app) {
const target = app || appOrVue.config.globalProperties || appOrVue.prototype
if (typeof plugin === 'function') {
plugin(target)
} else if (plugin.install) {
plugin.install(target)
}
}
}
}
This utility function detects the environment and applies the plugin appropriately, whether it's running in a Vue 2 context with Vue.prototype or a Vue 3 context with app.config.globalProperties. This approach is valuable for plugin authors maintaining compatibility across Vue versions or for teams in the middle of a migration who need their existing plugins to work in both environments.
Best Practices
When to Use Global Properties
Global properties are well-suited for application-wide utilities, shared services, and configuration that genuinely benefit from universal access. However, they should be used judiciously to avoid creating implicit dependencies that make code harder to test and reason about. The key is distinguishing between truly global concerns and feature-specific logic.
Appropriate use cases:
- API clients and service layer objects that need consistent configuration across all components
- Authentication state and user context that affects application behavior globally
- Application-wide configuration like feature flags, API endpoints, and environment settings
- Shared utility functions and formatters used throughout the application
- Third-party library instances that benefit from single instantiation
Cases where alternatives are better:
- Component-specific state should remain local to that component
- Feature-scoped logic is better handled through composables for better organization
- Shareable business logic benefits from composables or dedicated stores for maintainability
Performance Considerations
Global properties are evaluated once at application initialization and shared across all component instances, making them memory-efficient for commonly-used resources. However, be mindful of performance implications:
- Lazy initialization - Complex objects should be initialized efficiently to avoid blocking application startup
- Memory footprint - Avoid storing large objects globally when not needed, as they remain in memory for the application lifetime
- Tree shaking - Use named imports where possible for better bundler optimization and smaller bundle sizes
When implementing global properties, consider using lazy initialization patterns for expensive operations and ensure you're not inadvertently increasing your application's memory footprint with unnecessary global state. Following these patterns as part of a comprehensive /services/web-development/ strategy ensures applications remain performant and maintainable.
Modern Alternatives
Composables as the Preferred Approach
For new Vue 3 applications, composables often provide a cleaner alternative to global properties. As explained in the Vue.js Application API and demonstrated by advanced patterns from Vue Examples, composables offer better type inference, easier testing, and clearer dependency chains compared to global properties. They also align better with the Composition API philosophy of explicitly defining and composing functionality.
// composables/useApi.js
import { apiClient } from '../services/api'
export function useApi() {
const getUsers = async () => {
const response = await apiClient.get('/users')
return response.data
}
const createUser = async (userData) => {
const response = await apiClient.post('/users', userData)
return response.data
}
return { getUsers, createUser }
}
// Component.vue
<script setup>
import { useApi } from '../composables/useApi'
const { getUsers } = useApi()
const users = await getUsers()
</script>
Composables encourage a more modular architecture where dependencies are explicitly imported rather than accessed implicitly through the global scope. This makes components easier to test, reason about, and maintain over time. For complex Vue 3 applications, our team can help architect solutions using composables and modern patterns for better maintainability.
Provide/Inject for Dependency Sharing
For cases where you need to share dependencies across a component subtree without full application scope, Vue's Provide/Inject pattern offers explicit dependency chains while still avoiding prop drilling. This is particularly useful for feature-specific dependencies that should only be available within certain component hierarchies:
// ParentComponent.vue
<script setup>
import { provide } from 'vue'
import { apiClient } from '../services/api'
provide('api', apiClient)
</script>
// ChildComponent.vue
<script setup>
import { inject } from 'vue'
const api = inject('api')
const users = await api.get('/users')
</script>
Provide/Inject provides the explicit dependency declaration of composables while offering scoped availability. This makes it easier to understand where dependencies come from and allows for different implementations at different levels of the component tree.
Frequently Asked Questions
Conclusion
Vue.js global properties via app.config.globalProperties provide a straightforward mechanism for sharing utilities, services, and configurations across all components in your application. While modern alternatives like composables and Provide/Inject offer advantages in specific scenarios--particularly around type safety, testability, and explicit dependency management--global properties remain valuable for truly application-wide resources like API clients and shared utilities.
Use global properties thoughtfully, maintaining clear naming conventions with the $ prefix to indicate built-in Vue conventions. Consider TypeScript augmentation for better developer experience and type safety, and document your global properties thoroughly for team members. When starting new projects, evaluate whether composables might provide a cleaner architecture, but don't hesitate to use global properties when they genuinely simplify your application structure. Need expert guidance on implementing Vue.js best practices? Our /services/web-development/ team specializes in building scalable Vue.js applications with clean, maintainable architectures.
Sources
- Vue.js Application API - Official documentation for app.config.globalProperties including type signatures and implementation examples
- LogRocket Blog: Accessing Vue.js properties globally - Practical implementation guide with real-world examples and use cases
- Vue 3 Migration Guide: Global API - Migration patterns from Vue 2 to Vue 3 global API changes
- Vue Examples: Global Properties Patterns - Advanced patterns and best practices for global properties usage