Vue 3 breaking changes checklist

Every change below can break or silently change a Vue 2 app when it runs on Vue 3. vueleap checks all of them automatically and links each one to the official migration guide.

41 checks, 8 with safe automatic fixes. Generated from vueleap 0.1.2.

Instead of reading the list, run npx vueleap in your project to see which of these apply, with file and line numbers.

Templates

RuleSeverityWhat changes@vue/compat flagAuto fixDocs
filterserrorFilters are removed
Filters ({{ price | currency }}, Vue.filter, the filters option) no longer exist. Replace them with method calls, computed properties or global properties.
COMPILER_FILTERS FILTERSNoGuide
hook-eventswarninghook: lifecycle events are renamed
Listening to a child lifecycle with @hook:mounted becomes @vue:mounted. $on('hook:...') no longer works.
INSTANCE_EVENT_HOOKSYesGuide
sync-modifiererror.sync is replaced by v-model:prop
:title.sync="value" becomes v-model:title="value". The child keeps emitting update:title.
COMPILER_V_BIND_SYNCYesGuide
native-modifierwarningThe .native modifier is removed
Listeners not declared in the child emits option are added to its root element. Remove .native and declare the events the child really emits.
COMPILER_V_ON_NATIVENoGuide
keycode-modifierserrorKeyCode modifiers are removed
Numeric modifiers such as @keyup.13 must use key names such as @keyup.enter.
V_ON_KEYCODE_MODIFIERYesGuide
functional-componentserrorFunctional components changed
The functional attribute on <template> and the functional: true option are gone. Use a normal component (the performance gap is negligible) or a plain function.
COMPONENT_FUNCTIONALNoGuide
inline-templateerrorinline-template is removed
Move the inner markup into the component itself, or pass it through a default slot.
COMPILER_INLINE_TEMPLATENoGuide
template-v-for-keyerrorKey must be on <template v-for>
With <template v-for>, the key belongs on the <template> tag. Keys on its children are a compile error in Vue 3.
noneNoGuide
v-if-v-forerrorv-if now has higher priority than v-for
On the same element, v-if is evaluated first, so it cannot use the v-for variable. Filter the list in a computed property or move v-if to a wrapper.
COMPILER_V_IF_V_FOR_PRECEDENCENoGuide
v-bind-object-orderwarningv-bind="object" is order sensitive
Attributes declared before v-bind="obj" can now be overridden by the object. Move v-bind="obj" first if the explicit attributes should win, as they did in Vue 2.
COMPILER_V_BIND_OBJECT_ORDERNoGuide
transition-group-rootinfo<transition-group> renders no wrapper
Without a tag prop, <transition-group> no longer renders a <span>. Add tag="span" if your CSS relies on it.
TRANSITION_GROUP_ROOTNoGuide
deprecated-slot-syntaxerrorslot and slot-scope attributes are removed
The slot, slot-scope and scope attributes were deprecated in Vue 2.6 and removed in Vue 3. Use v-slot (or #name).
noneNoGuide
is-on-elementwarningis on native elements needs the vue: prefix
<tr is="my-row"> now creates a customized built-in element. Use is="vue:my-row" to render a Vue component.
COMPILER_IS_ON_ELEMENTNoGuide

Scripts and component options

RuleSeverityWhat changes@vue/compat flagAuto fixDocs
listenerserror$listeners is removed
Event listeners are now part of $attrs. v-on="$listeners" can usually be dropped when v-bind="$attrs" is present.
INSTANCE_LISTENERSNoGuide
scoped-slotserror$scopedSlots is removed
All slots are exposed on $slots as functions. $scopedSlots.x becomes $slots.x.
INSTANCE_SCOPED_SLOTSYesGuide
event-emittererror$on, $off and $once are removed
Instances are no longer event emitters, so event buses built on new Vue() stop working. Use props and emits, provide/inject, a store, or a small library such as mitt.
INSTANCE_EVENT_EMITTERNoGuide
set-deleteerror$set, $delete, Vue.set and Vue.delete are removed
Vue 3 reactivity is based on Proxy, so plain assignment and the delete operator are tracked. Replace this.$set(obj, key, value) with obj[key] = value.
GLOBAL_SET GLOBAL_DELETE INSTANCE_SET INSTANCE_DELETENoGuide
childrenerror$children is removed
Use template refs to reach child component instances.
INSTANCE_CHILDRENNoGuide
destroyerror$destroy is removed
Components can no longer destroy themselves. Unmount the app with app.unmount() or remove the component with v-if.
INSTANCE_DESTROYNoGuide
global-mounterrornew Vue() is replaced by createApp()
Create the root with createApp(App) and mount it with app.mount('#app').
GLOBAL_MOUNTNoGuide
global-apierrorGlobal Vue API moved to the app instance
Vue.component, Vue.use, Vue.mixin and Vue.directive become app.component, app.use, app.mixin and app.directive. Vue.nextTick and Vue.observable become named imports (nextTick, reactive).
GLOBAL_OBSERVABLE GLOBAL_PRIVATE_UTILNoGuide
global-prototypeerrorVue.prototype is replaced by app.config.globalProperties
Move Vue.prototype.$http = http to app.config.globalProperties.$http = http, or use provide/inject.
GLOBAL_PROTOTYPENoGuide
global-extenderrorVue.extend is removed
Use defineComponent for type inference, the extends option for inheritance and createApp to mount.
GLOBAL_EXTENDNoGuide
config-production-tipwarningVue.config.productionTip is removed
The option no longer exists. The statement can simply be deleted.
CONFIG_PRODUCTION_TIPYesGuide
config-ignored-elementswarningVue.config.ignoredElements is replaced by isCustomElement
Use compilerOptions.isCustomElement in your build config (or app.config.compilerOptions.isCustomElement with the runtime compiler). It takes a function instead of strings or regular expressions.
CONFIG_IGNORED_ELEMENTSNoGuide
config-key-codeserrorVue.config.keyCodes is removed
Custom key code aliases are gone. Use kebab-case key names such as @keyup.page-down.
CONFIG_KEY_CODESNoGuide
global-configwarningVue.config moved to app.config
Global configuration now lives on app.config. Some options (silent, devtools) were removed.
CONFIG_SILENT CONFIG_DEVTOOLS CONFIG_OPTION_MERGE_STRATSNoGuide
destroy-hookserrorbeforeDestroy and destroyed are renamed
beforeDestroy is now beforeUnmount and destroyed is now unmounted. The old hooks are silently ignored.
OPTIONS_BEFORE_DESTROY OPTIONS_DESTROYEDYesGuide
directive-hookserrorCustom directive hooks are renamed
Directive hooks follow the component lifecycle: bind is beforeMount, inserted is mounted, componentUpdated is updated, unbind is unmounted, and update was removed.
CUSTOM_DIRYesGuide
component-v-modelerrorv-model on components uses modelValue
A component used with v-model now receives modelValue and must emit update:modelValue. The value prop, the input event and the model option no longer apply.
COMPONENT_V_MODELNoGuide
render-function-herrorRender functions no longer receive h
Import h from vue instead of taking it as an argument. The VNode props shape is also flatter (on, attrs and domProps are gone).
RENDER_FUNCTIONNoGuide
attrs-class-styleinfo$attrs now includes class and style
Check components that forward $attrs, especially with inheritAttrs: false, because class and style now travel with them.
INSTANCE_ATTRS_CLASS_STYLENoGuide
data-objecterrordata must be a function
Declaring data as a plain object is no longer allowed, including on the root instance. Use data() { return { ... } }.
OPTIONS_DATA_FNNoGuide
watch-arrayinfoArray watchers need deep for mutations
Watching an array only fires when the array is replaced. Add deep: true if you rely on push, splice and friends.
WATCH_ARRAYNoGuide
composition-api-pluginwarning@vue/composition-api is built in
Import the Composition API from vue and remove the plugin. Some helpers (set, del) have no Vue 3 equivalent.
noneNoGuide

Styles

RuleSeverityWhat changes@vue/compat flagAuto fixDocs
transition-classeswarningTransition classes renamed
.v-enter is now .v-enter-from and .v-leave is now .v-leave-from. The enter-class and leave-class props are now enter-from-class and leave-from-class.
TRANSITION_CLASSESYesGuide

Dependencies

RuleSeverityWhat changes@vue/compat flagAuto fixDocs
vue-versionwarningVue 2 dependency
Upgrade vue to version 3. During the migration, alias vue to @vue/compat to run Vue 2 code on Vue 3.
noneNoGuide
vue2-toolingwarningVue 2 build or test tooling
Compilers, loaders and test utilities are versioned with Vue. Each one has a Vue 3 replacement.
noneNoGuide
vue-router-v3errorvue-router 3 does not support Vue 3
Upgrade to vue-router 4: new VueRouter() becomes createRouter(), mode becomes history: createWebHistory(), and catch-all routes need a custom regex.
noneNoGuide
vuex-v3errorVuex 3 does not support Vue 3
Upgrade to Vuex 4 (createStore), or move to Pinia, the official recommendation for new Vue 3 code.
noneNoGuide
vue2-librarieserrorVue 2 only library
This library only supports Vue 2. Each finding names its Vue 3 successor.
noneNoGuide

No check matches this search.

How vueleap detects them

Templates are parsed with @vue/compiler-dom (the Vue 3 compiler parser, which still understands Vue 2 syntax), scripts with @babel/parser (JavaScript, TypeScript, JSX and decorators), styles with a comment aware scanner, and dependencies from package.json. Component options are only checked on objects that really look like components, so a { destroyed: true } flag is not mistaken for a lifecycle hook.

More guides