How to debug Vue with DevTools
Debugging Vue applications with Vue DevTools provides powerful inspection of components, state, events, routing, and performance profiling. As the creator of CoreUI with over 12 years of Vue.js experience since 2014, I’ve used Vue DevTools extensively for debugging complex applications. Vue DevTools browser extension integrates with Chrome and Firefox, offering real-time component inspection and time-travel debugging. This approach makes debugging Vue applications significantly faster with visual component hierarchy and reactive data tracking.
Install Vue DevTools browser extension to inspect component state, debug reactivity, and profile performance in Vue applications.
Installing Vue DevTools:
# Chrome Web Store
# Search for "Vue.js devtools" and install
# Firefox Add-ons
# Search for "Vue.js devtools" and install
# Standalone Electron app
npm install -g @vue/devtools
vue-devtools
Enable in development:
// main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// Enable DevTools in development
if (import.meta.env.MODE === 'development') {
app.config.performance = true
app.config.devtools = true
}
app.mount('#app')
Component inspection:
<script setup>
import { ref, computed, watch } from 'vue'
// All these are visible in DevTools
const count = ref(0)
const message = ref('Hello')
const doubled = computed(() => count.value * 2)
watch(count, (newVal, oldVal) => {
console.log(`Count changed from ${oldVal} to ${newVal}`)
})
const increment = () => {
count.value++
}
// Component name for DevTools (useful for production builds)
defineOptions({
name: 'CounterComponent'
})
</script>
<template>
<div>
<p>Count: {{ count }}</p>
<p>Doubled: {{ doubled }}</p>
<button @click="increment">Increment</button>
</div>
</template>
DevTools features:
<script setup>
import { ref, reactive, provide, inject } from 'vue'
// 1. Component Tree - View component hierarchy
// Click components to inspect props, data, computed
// 2. Component State - Inspect reactive state
const state = reactive({
user: {
name: 'John',
email: '[email protected]'
},
settings: {
theme: 'dark',
notifications: true
}
})
// 3. Props inspection
const props = defineProps({
title: String,
count: Number
})
// 4. Computed properties - See cached values
const fullName = computed(() => {
return `${state.user.name} (${state.user.email})`
})
// 5. Provide/Inject - Track dependency injection
provide('theme', state.settings.theme)
const theme = inject('theme')
// 6. Edit state in DevTools - Modify values live
const editable = ref('Edit me in DevTools')
// 7. Timeline - Track events, mutations, component updates
const emit = defineEmits(['update', 'delete'])
const handleUpdate = () => {
emit('update', { id: 1, name: 'Updated' })
}
</script>
Performance profiling:
<script setup>
import { ref, onMounted, onUpdated } from 'vue'
// Enable performance tracking
onMounted(() => {
console.log('Component mounted')
})
onUpdated(() => {
console.log('Component updated')
})
// DevTools Performance Tab shows:
// - Component render time
// - Lifecycle hook timing
// - Update frequency
// - Memory usage
const items = ref(Array.from({ length: 1000 }, (_, i) => ({
id: i,
name: `Item ${i}`
})))
// Use DevTools to profile this expensive operation
const sortItems = () => {
performance.mark('sort-start')
items.value = [...items.value].sort((a, b) =>
a.name.localeCompare(b.name)
)
performance.mark('sort-end')
performance.measure('sort', 'sort-start', 'sort-end')
}
</script>
Routing inspection:
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'Home',
component: () => import('./views/Home.vue')
},
{
path: '/users/:id',
name: 'UserProfile',
component: () => import('./views/UserProfile.vue'),
meta: { requiresAuth: true }
}
]
})
// DevTools Router Tab shows:
// - Current route
// - Route params
// - Route meta
// - Navigation history
// - Route guards execution
export default router
Vuex/Pinia store inspection:
// stores/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
user: null,
isAuthenticated: false,
preferences: {
theme: 'light',
language: 'en'
}
}),
getters: {
fullName: (state) => {
return state.user ? `${state.user.firstName} ${state.user.lastName}` : ''
}
},
actions: {
setUser(user) {
this.user = user
this.isAuthenticated = true
// DevTools shows this mutation in timeline
},
updatePreferences(preferences) {
this.preferences = { ...this.preferences, ...preferences }
}
}
})
// DevTools Pinia Tab shows:
// - All stores
// - Current state
// - Getters values
// - Actions history
// - Time-travel debugging
Custom DevTools plugin:
// devtools-plugin.js
export function setupDevTools(app) {
if (import.meta.env.MODE === 'development' && window.__VUE_DEVTOOLS_GLOBAL_HOOK__) {
app.config.globalProperties.$devtools = {
log: (message, data) => {
console.log('[DevTools]', message, data)
// Send custom data to DevTools
window.__VUE_DEVTOOLS_GLOBAL_HOOK__.emit('custom-log', {
message,
data,
timestamp: Date.now()
})
}
}
}
}
// Usage in component
const devtools = inject('$devtools')
devtools?.log('User action', { action: 'click', target: 'button' })
Debugging tips:
<script setup>
import { ref, watchEffect } from 'vue'
const count = ref(0)
// 1. Use DevTools breakpoints
// Click "Bug" icon in DevTools to pause on component updates
// 2. Inspect reactive dependencies
watchEffect(() => {
console.log('Count changed:', count.value)
// DevTools shows what triggered this watcher
})
// 3. Edit state live
// Change values in DevTools to test different states
// 4. Time-travel debugging
// Use timeline to replay component state changes
// 5. Export state
// Right-click component in DevTools > "Export state to console"
// 6. Force update
// Right-click component > "Force update" to trigger re-render
const debugHelper = () => {
// DevTools can intercept and inspect this
console.log('Current state:', count.value)
}
</script>
Best Practice Note
Install Vue DevTools from official Chrome or Firefox stores. Enable devtools in development mode only. Use component tree to understand component hierarchy. Inspect reactive state to debug reactivity issues. Use timeline to track events and mutations. Profile performance to identify slow components. Use time-travel debugging to replay state changes. Export component state for testing. This is how we debug CoreUI Vue applications—Vue DevTools for real-time component inspection, performance profiling, and time-travel debugging making development significantly faster and more efficient.



