1. Take an inventory of breaking changes
Run vueleap at the root of the project. It reads .vue, JavaScript, TypeScript and style files plus package.json, skips node_modules, dist and anything in .gitignore, and groups findings by rule.
# run it once, nothing to install
npx vueleap
# or add it to the project
npm install --save-dev vueleap# run it once, nothing to install
pnpm dlx vueleap
# or add it to the project
pnpm add --save-dev vueleap# run it once, nothing to install
yarn dlx vueleap
# or add it to the project
yarn add --dev vueleap# run it once, nothing to install
bunx vueleap
# or add it to the project
bun add --dev vueleapAdd --html report.html to also get a shareable report.
Every finding has a severity: error breaks at compile time or runtime, warning changes behavior, info deserves a review. The summary ends with an effort score to compare projects or track progress.
2. Upgrade the build tooling
Vue 3 single file components are compiled by @vue/compiler-sfc, which ships with vue. Remove vue-template-compiler, use vue-loader 17 with webpack or Vue CLI 5, or @vitejs/plugin-vue with Vite. vueleap reports these under vue2-tooling.
3. Install Vue 3 with the migration build
npm install vue@^3.5 @vue/compat@^3.5
npm uninstall vue-template-compilerAlias vue to @vue/compat and enable compat mode in the template compiler. vueleap prints this configuration with only the flags your project needs, running everything else in Vue 3 mode (MODE: 3):
// vite.config.js
import vue from '@vitejs/plugin-vue'
export default {
resolve: { alias: { vue: '@vue/compat' } },
plugins: [
vue({
template: {
compilerOptions: {
compatConfig: { MODE: 3, COMPILER_FILTERS: true, COMPILER_V_BIND_SYNC: true },
},
},
}),
],
}// main.js
import { configureCompat } from 'vue'
configureCompat({
MODE: 3,
GLOBAL_MOUNT: true,
INSTANCE_EVENT_EMITTER: true,
FILTERS: true,
})Read @vue/compat build flags explained for what each flag does.
4. Apply the safe automatic fixes
Some changes are pure renames. vueleap rewrites them while preserving formatting, and shows a diff first:
npx vueleap --fix # preview
npx vueleap --fix --write # applyThat covers beforeDestroy and destroyed, custom directive hooks, $scopedSlots, transition class names, keyCode modifiers with a single key name, .sync to v-model:prop, @hook: events and Vue.config.productionTip.
5. Fix the rest, rule by rule
- Replace
new Vue()withcreateApp()and moveVue.use,Vue.component,Vue.directiveandVue.prototypeto the app instance. - Remove filters and replace the event bus.
- Update components used with v-model to
modelValueandupdate:modelValue. - Rewrite render functions to import
hfromvue, and replace$listenersand$children.
The breaking changes checklist links every rule to the official guide.
6. Upgrade the ecosystem
Move to vue-router 4 and to Vuex 4 or Pinia. Replace Vue 2 only UI libraries: BootstrapVue with bootstrap-vue-next, Vuetify 2 with Vuetify 3, Element UI with Element Plus. vueleap lists them from package.json with the suggested successor.
7. Turn compat off and keep it off
Remove each compat flag once vueleap no longer reports the matching rule. When the list is empty, drop the alias and @vue/compat. Then keep the codebase clean in CI:
npx vueleap --fail-on errorFrequently asked questions
It depends on how much the code relies on removed APIs and on Vue 2 only libraries. Run npx vueleap to get an inventory and an effort score: each finding adds a weight, and fixable findings count for a tenth. UI libraries such as Vuetify 2 or BootstrapVue usually dominate the total.
Yes. The @vue/compat migration build runs Vue 2 style code on Vue 3, and each compat flag can be turned off once the matching code is fixed. vueleap prints the minimal set of flags your project needs.
No. The Options API is fully supported in Vue 3. Migrate first, then adopt the Composition API where it helps.