Using Vue's @vue/compat migration build, in what order do you upgrade a Vue 2 app, its router and its store, and why that order?
answer
- compile before you run
- the one change nobody warns about
- entry point, then ecosystem
- router-view wrappers wait for router 4
- warnings last, one ID at a time
basics
~20 sMake it compile first (tooling, package swap, alias, compile-time errors like filters), then run it, rename transition classes by hand, switch to createApp, upgrade store and router to their Vue 3 versions, clear warnings per ID, and remove compat.
solid answer
~50 sThe migration guide's order follows what blocks what. On Vue 2.6, move off the deprecated slot syntax. Then upgrade tooling, swap `vue` to 3.x with `@vue/compat` and `@vue/compiler-sfc`, alias `vue` and set compiler `MODE: 2`. **Compile-time errors come first** — filters, `v-if`/`v-for` precedence — because nothing runs until templates compile. Once it boots, **rename transition classes** (`v-enter` → `v-enter-from`) by search, since that is the only change with no warning. Switch the entry to `createApp`, then upgrade **Vuex to 4** and **Vue Router to 4**: many warnings originate in those dependencies, and `<transition>`/`<keep-alive>` around `<router-view>` do not work until Router 4, which then needs its scoped-slot syntax. Only then pick off your own warnings one ID at a time, using per-component `compatConfig` where Vue 2 and 3 behaviours conflict, and remove the alias when warnings and dependencies allow.
go deeper
Know the broad order: make it compile, make it run, upgrade router and store, then fix warnings and remove the migration build.
Explain why compile-time errors come before runtime warnings and why transition class names need a manual search.
Sequence a real upgrade: tooling, alias and compiler mode, compile fixes, boot, transitions, createApp, Vuex 4, Router 4, per-ID warning work with per-component compatConfig, and a release plan that ships on compat meanwhile.
Turn the sequence into milestones with owners and exit criteria, deciding which steps may ship independently and how to keep feature work flowing while warnings are cleared.
## The principle: fix what blocks the next step A Vue 2 to Vue 3 upgrade through the **migration build** (`@vue/compat`) is a sequence where each stage unblocks the next: the app must **install**, then **compile**, then **run**, then have its **ecosystem** upgraded, and only then can the long tail of **deprecation warnings** be worked down. Doing the steps out of order either blocks you or buries real signals in noise. ## Before touching Vue 3 - On **Vue 2.6**, replace the deprecated named and scoped slot syntax with `v-slot`, which 2.6 already supports. This is a pure Vue 2 change and shrinks the later diff. - **Upgrade the tooling**: for a custom webpack setup, `vue-loader` `^16.0.0`; for the CLI, the latest `@vue/cli-service`; or move the build to Vite with a Vue 2 plugin first. ## The ordered workflow 1. **Swap the packages**: `vue` to 3.x, `@vue/compat` at the same version, `vue-template-compiler` replaced by `@vue/compiler-sfc`. 2. **Alias and configure**: alias `vue` to `@vue/compat`, pass `compatConfig: { MODE: 2 }` to the template compiler, and add the TypeScript declaration that exposes the default export if you use TypeScript. 3. **Fix compile-time errors and warnings**: filters in templates, `v-if`/`v-for` precedence, keys on `<template v-for>`, `<template functional>`. Once compiler warnings are gone you can also switch the compiler to Vue 3 mode. 4. **Boot the app** — if it is not blocked by a dependency on Vue 2 internals, IE11 or a custom SSR setup. 5. **Rename transition classes**: search for `-enter` and `-leave` selectors and move to `v-enter-from`, `v-leave-from` and the prop equivalents. 6. **Switch the entry point** to `createApp(App).mount('#app')`. 7. **Upgrade Vuex to 4**, the Vue 3 version of the store. 8. **Upgrade Vue Router to 4**, and move `<transition>` and `<keep-alive>` around `<router-view>` to its scoped-slot syntax. 9. **Work the warnings**, one deprecation ID at a time, using per-component `compatConfig` where Vue 2 and Vue 3 behaviour are mutually exclusive. 10. **Remove the migration build** when all warnings are fixed and no dependency still needs Vue 2 behaviour. ## Why this order | step | why it sits there | |---|---| | compile-time fixes before running | nothing renders until every template compiles | | transition classes right after boot | the only change with no warning, so it is easy to forget once the console becomes the to-do list | | store and router before the warning list | many warnings originate in those dependencies, and `<router-view>` wrappers stay broken until Router 4 | | per-ID warning work next | with dependencies current, what remains is your own code | | removing compat last | a single leftover Vue 2 dependency can keep you on it | The transition step has a subtle reason. Under compat, the legacy `v-enter` and `v-leave` classes are **still applied alongside the new ones**, so the CSS keeps working and nothing complains. The day the alias is removed, those selectors silently stop matching. ## Working the warning list - Filter the browser console to **one deprecation ID** at a time; negated filters such as `-GLOBAL_MOUNT` hide IDs you have finished. - **Fix warnings from your own source first**; a warning's component or stack trace shows whether it comes from a dependency. - Use `'suppress-warning'` for debt you have deliberately deferred, so it stops hiding new problems. - For conflicting behaviour such as render functions or the component `v-model` contract, set `compatConfig` on each component as it is converted. ## Shipping along the way The migration guide allows shipping an app that runs on the migration build to production before the migration is complete, with a small performance and size overhead. That lets the sequence above run across several releases instead of one long-lived branch. Natural release points in the sequence: - after the **2.6 slot-syntax cleanup** and tooling upgrade, which are safe on Vue 2; - after the app **boots on the migration build** with transitions fixed and the `createApp` entry in place; - after the **store and router** upgrades, which change behaviour the most and deserve their own release; - after each batch of **warning IDs** is cleared, and finally when the alias is removed. Because deprecation warnings print only in development builds, each release's regression safety comes from the test suite and review, not from the production console.
- Why is renaming transition classes a manual search rather than something the warning list will remind you about?`TRANSITION_CLASSES` is compat-only with no warning. Under the migration build, the legacy `v-enter`/`v-leave` classes are applied alongside the new `-from` classes, so CSS keeps working and the console is silent. Once the alias is removed, the old selectors stop matching, so you search stylesheets for `-enter` and `-leave` instead.
- Do you have to finish the whole sequence before releasing?No. An app that runs on the migration build can go to production before the migration is complete; the guide calls the overhead small. Teams often have to, when a dependency still needs Vue 2 behaviour. The aim remains reaching the standard build, so track the remaining warning IDs as the release-to-release progress measure.
saying these in an interview costs you the question
- Upgrade Vue Router to 4 while still on Vue 2, before swapping in the migration build.
- Fix every runtime deprecation warning before the app first boots on @vue/compat.
- A clean console means the migration is finished and compat can be removed.
- Fix the warnings coming from dependencies before those in your own code.
- Drop the migration build as soon as the app boots on Vue 3.