Vue 3 migrations have a reputation for being difficult. But the difficulty isn't random—the same problems appear in project after project. Understanding these common blockers before you start is the difference between a migration that takes weeks and one that drags on for months.
This guide covers the 7 blockers most likely to derail your migration, how to identify them early, and proven strategies for each. For timeline and cost context, see our migration timeline guide and cost estimation guide.
The 7 Blockers at a Glance
| # | Blocker | Impact | Timeline Effect |
|---|---|---|---|
| 1 | Vuetify 2 Deep Integration | Critical | +50-100% |
| 2 | Abandoned Dependencies | Critical | +20-40% |
| 3 | Mixin Spaghetti | High | +15-30% |
| 4 | Complex Vuex Architecture | High | +15-30% |
| 5 | Custom Webpack Hell | Medium | +10-20% |
| 6 | Zero Test Coverage | High | +20-40% |
| 7 | Part-Time Migration Team | Critical | +100-150% |
Vuetify 2 Deep Integration
The #1 migration killer
Impact: Can double migration timeline and cost
Why This Is So Painful
Vuetify 2 and Vuetify 3 have completely different APIs. Component names, prop names, slot names, event names—everything changed. Teams using Vuetify heavily (100+ components) face a near-complete rewrite of their UI layer.
Warning Signs
- • More than 50 files importing Vuetify components
- • Custom Vuetify theme with SCSS overrides
- • Use of deprecated Vuetify components (v-content, v-layout)
- • Heavy reliance on Vuetify's grid system
The Solution
Create a component-by-component migration map before starting. Migrate in isolation—don't try to run @vue/compat with Vuetify. Budget 40-60% of your migration time just for Vuetify.
Read our Vuetify Migration Playbook →Abandoned Dependencies
The hidden landmines in package.json
Impact: Blocks migration until alternatives are found and implemented
Why This Happens
The average Vue 2 project has 5-8 Vue-specific npm packages that don't support Vue 3. Some are abandoned, some never got updated, some have Vue 3 versions with completely different APIs. Each one needs to be addressed before migration can complete.
Commonly Abandoned Packages
- × vue-moment
- × vue-clipboard2
- × vue-lazyload
- × vue-meta (v2)
- × vue-scrollto
- × vue-notification
- × vue-js-modal
- × vue-multiselect
The Solution
Run a dependency audit before estimating timeline. For each Vue-specific package, determine: Does it have a Vue 3 version? Is there an alternative? Can we remove it entirely? Can we build it ourselves?
npm ls | grep vueList all Vue-related packages and check each one for Vue 3 compatibility.
Mixin Spaghetti
When code reuse becomes code confusion
Impact: 2-4 weeks of refactoring before migration can proceed
Why This Is Problematic
Mixins were Vue 2's answer to code reuse. The problem? They create implicit dependencies, naming conflicts, and untraceable data flow. Codebases with 20+ mixins, some chained 3-4 levels deep, become nearly impossible to migrate safely.
The Mixin Problem
// Where does `formatDate` come from?
// Where does `userData` come from?
// What if two mixins both define `loading`?
export default {
mixins: [FormMixin, ValidationMixin, UserMixin, AnalyticsMixin],
computed: {
displayDate() {
return this.formatDate(this.userData.created) // 🤷
}
}
}The Solution
Convert mixins to composables before or during migration. Composables have explicit imports—you can see exactly where each piece of functionality comes from.
// Composable: explicit, traceable, typed
import { useForm } from '@/composables/useForm'
import { useUser } from '@/composables/useUser'
import { formatDate } from '@/utils/dates'
const { userData } = useUser()
const { validate, errors } = useForm()Complex Vuex Architecture
More than just "install Pinia"
Impact: 2-4 weeks to migrate to Pinia, longer with plugins
When Vuex Gets Complicated
Simple Vuex stores migrate easily. But stores with 15+ modules, nested namespacing, custom plugins, and middleware are a different story. Custom Vuex plugins for features like undo/redo or persistence can take weeks to reimplement in Pinia.
Complexity Indicators
- • More than 10 Vuex modules
- • Nested modules (modules inside modules)
- • Custom Vuex plugins (persistence, logging, etc.)
- • Heavy use of
rootGettersand cross-module dispatch - • Dynamic module registration
The Solution
Migrate one module at a time. Pinia and Vuex can coexist during migration. Start with leaf modules (no dependencies), work toward root modules.
Read our Vuex to Pinia Migration Guide →Custom Webpack Hell
Years of accumulated build complexity
Impact: 1-2 weeks of build tool debugging
The Build Tool Dilemma
Teams that ejected from Vue CLI or added heavy customizations face a choice: migrate the entire Webpack config to Vite, or update it for Vue 3. Neither is fun. Configs with 500+ lines of custom Webpack rules take significant time to untangle.
Common Customizations
- • Custom loaders for specific file types
- • Module federation or micro-frontend setup
- • Specific optimization plugins
- • Custom dev server middleware
- • Legacy browser polyfill chains
The Solution
Document every customization before starting. For each one, determine: Is it still needed? Is there a Vite equivalent? Can we simplify? Consider this an opportunity to clean up years of accumulated build complexity.
Zero Test Coverage
Flying blind through a major rewrite
Impact: Higher risk of production bugs, longer QA cycles
The Testing Reality
Many Vue 2 codebases have less than 20% test coverage, and some have zero tests. Without tests, you're flying blind during migration—every change could break something, and you won't know until a user reports it.
The Testing Catch-22
"We can't migrate without tests, but we can't write Vue 2 tests when we're about to migrate to Vue 3."
This is a real dilemma. The answer depends on your risk tolerance and timeline.
The Solution
Write E2E tests first (Cypress/Playwright). These survive the migration and catch regressions in user flows.
Migrate first, then write tests for Vue 3. Faster, but riskier. Requires thorough manual QA.
Focus on critical path tests only. Identify your 10 most important user flows and test those.
Part-Time Migration Team
The organizational blocker
Impact: 2-3x longer timeline, higher total cost, team burnout
Why Part-Time Fails
Most teams attempt migration while simultaneously shipping features. "We'll work on the migration when we have time." The problem: there's never time. Context switching destroys momentum. Migrations drag on for months, sometimes over a year.
The Part-Time Penalty
Dedicated Team
8 weeks
Focused, consistent progress
Part-Time (50%)
20+ weeks
Context switching, stalls
The Solution
Treat migration as a project, not a side task. Either dedicate developers full-time for a shorter period, or hire specialists to handle it while your team focuses on features.
See realistic timeline estimates →How to Identify Your Blockers Early
The worst time to discover a blocker is mid-migration. Here's how to find them before you commit to a timeline:
Run a dependency audit
Check every Vue-related package for Vue 3 support. Create a spreadsheet with status: Compatible / Needs Replacement / Needs Custom Solution.
Count your Vuetify/BootstrapVue components
grep -r "v-btn\|v-card\|v-dialog" --include="*.vue" | wc -l — If this number is high, plan accordingly.
Map your mixins
List every mixin and which components use them. Identify naming conflicts and dependency chains.
Document your Vuex complexity
Count modules, identify plugins, check for nested namespacing and dynamic registration.
Review your build configuration
Identify all custom Webpack/Vue CLI configurations. Note any that will need special attention.
Check test coverage
Run coverage report. If it's low, factor in additional QA time or write E2E tests first.
Don't Want to Do This Yourself?
Our Migration Readiness Audit identifies all 7 blockers in your codebase, provides specific remediation strategies, and gives you a realistic timeline and fixed-price quote.
✓ All 7 blockers assessed ✓ Remediation strategies included ✓ Fixed-price quote
Conclusion
Every Vue 2 migration has challenges. But the difference between a migration that takes 8 weeks and one that drags on for 8 months usually comes down to whether these 7 blockers were identified early.
Vuetify integration. Abandoned packages. Mixin spaghetti. Complex Vuex. Webpack customization. No tests. Part-time teams. If you're planning a migration, audit your codebase for these issues before you estimate timeline and cost.
The blockers won't go away if you ignore them. But if you know they're coming, you can plan for them—and that makes all the difference.
