skip to content

Compat Build & Rollout

The @vue/compat migration build with configureCompat and per-component compatConfig, the 2.7 Composition API backport, and upgrade order. Interviewers probe how you ship an upgrade in stages.

part ofVue.jsoverview, primer and where to startread it →
on this pageshow

explore

questions

5

What is Vue's @vue/compat migration build, and how does it let a Vue 2 app run on Vue 3 during an upgrade?

level: middleimportance: should knowfreq 45%

answer

  1. a Vue 3 build wearing Vue 2 clothes
  2. which mode it starts in
  3. deprecation IDs in the dev console
  4. a bundler alias plus compiler options
  5. not every app is eligible

basics

~20 s

@vue/compat is a Vue 3 build that runs in Vue 2 mode by default: most public Vue 2 APIs keep working, and each changed feature logs a deprecation warning with an ID, so an app migrates one warning at a time.

solid answer

~50 s

The migration build is Vue 3 with configurable Vue 2-compatible behaviour. You move `vue` to 3.x, install `@vue/compat` at the same version, replace `vue-template-compiler` with `@vue/compiler-sfc`, alias `vue` to `@vue/compat` in the bundler, and set `compilerOptions.compatConfig: { MODE: 2 }` for SFC templates, because the template compiler otherwise defaults to Vue 3 behaviour. The runtime starts in `MODE: 2`, so Vue 2 APIs such as `new Vue()`, `$on` or `$listeners` still work, and in development each logs `(deprecation ID) …` with a link to the guide. A few changes are incompatible and must be fixed first (for example `v-if`/`v-for` precedence), and the transition class rename raises no warning at all. It covers only documented Vue 2 APIs, so dependencies built on Vue 2 internals, IE11 support or a custom SSR setup can block it. An app that runs on it can ship to production with a small overhead.

code

ts · 18 lines
ts
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  resolve: {
    alias: { vue: '@vue/compat' }
  },
  plugins: [
    vue({
      template: {
        compilerOptions: {
          compatConfig: { MODE: 2 }
        }
      }
    })
  ]
})

go deeper

for a junior

Know that @vue/compat is a Vue 3 build that runs Vue 2 code by default and prints deprecation warnings naming each feature that needs changing.

for a middle

Explain the wiring: same-version packages, the vue alias, and compatConfig MODE 2 in the compiler options because the compiler defaults to Vue 3. Name the four compatibility categories and the silent transition-class change.

for a senior

Judge eligibility before starting: dependencies on Vue 2 internals, IE11, custom SSR. Plan to collect warnings from dev and test runs, since production is silent.

for a principal

Treat the migration build as a funded bridge with an exit: decide whether shipping on it is acceptable, how long, and what signals mean the team can drop the alias.

## What the migration build is Upgrading from **Vue 2** to **Vue 3** means dealing with dozens of breaking changes: the global API moved to `createApp`, the component `v-model` contract changed, filters and the `$on` event API were removed, and more. Fixing them all before the app can boot again is a big-bang change. **`@vue/compat`**, which the official migration guide calls **the migration build**, removes that cliff: it is a build of Vue 3 with **configurable Vue 2-compatible behaviour** layered on top. Two properties make it useful: - it **runs in Vue 2 mode by default** — most public Vue 2 APIs behave exactly as before, with only a few exceptions; - every use of a feature that changed or was deprecated emits a **runtime deprecation warning** that names the feature with an ID, so the migration becomes a checklist rather than a guessing game. Compatibility can also be switched on or off **per feature** and **per component**, which is what makes an incremental upgrade possible. ## Wiring it in The migration guide's workflow for a webpack- or Vite-based app: 1. Upgrade tooling if needed (for example `vue-loader` to `^16.0.0`). 2. In `package.json`, move `vue` to Vue 3, add `@vue/compat` at the **same version**, and replace `vue-template-compiler` with `@vue/compiler-sfc`. 3. Alias `vue` to `@vue/compat` in the bundler, so every `import ... from 'vue'` — yours and your dependencies' — gets the compat build. 4. Pass `compilerOptions: { compatConfig: { MODE: 2 } }` to the SFC template compiler. The **template compiler defaults to Vue 3 behaviour** independently of the runtime, so without this, template-level Vue 2 behaviour is not preserved. 5. For TypeScript, add a declaration file that re-exposes Vue's default export and `configureCompat`, since Vue 3's typings have no default export. ## How the warnings work Each warning is printed as `(deprecation GLOBAL_MOUNT) ...` followed by a `Details:` link to the relevant migration-guide page. Useful behaviours: - warnings are **development-only**; a production build prints nothing, so collect them from the dev server and the test suite; - the same deprecation from the **same component type** is reported once, and repeats from other components are shortened to the ID and a count; - the browser console's filter, including negated filters such as `-GLOBAL_MOUNT`, lets you work through one ID at a time; - a warning's component trace shows whether it comes from your code or a dependency. ## Four kinds of compatibility | category | meaning | example | |---|---|---| | fully compatible | Vue 2 behaviour preserved, with a warning | `new Vue()`, `vm.$on`, `$listeners`, filters | | partially compatible | preserved with caveats | `$destroy` (root instance only), `this` in prop default factories | | incompatible | warning only; fix upfront | `v-if`/`v-for` precedence, `<template functional>` | | compat only | preserved, **no warning** | transition classes `v-enter` → `v-enter-from` | The last row is the trap: the transition class rename is the one change the build keeps working silently, so it has to be found with a search for `-enter` and `-leave` selectors. ## Who cannot use it The migration build only covers **publicly documented** Vue 2 behaviour. The guide lists these limitations: - dependencies that rely on **Vue 2 internals** or undocumented behaviour, most commonly private properties on VNodes — such libraries need their own Vue 3 versions; - **IE11**: Vue 3 does not support it, so an app that must support it stays on Vue 2; - **custom SSR**: possible, but much more involved — `vue-server-renderer` gives way to `@vue/server-renderer`, and Vue 3 has no bundle renderer. ## Shipping on it An app that runs on the migration build **can ship to production** before the migration is finished; the guide describes the performance and size overhead as small. That matters when a dependency still needs Vue 2 behaviour. It is still a bridge: the goal is to clear the warnings, switch the app to Vue 3 behaviour and then drop the alias for the standard `vue` build. Two settings make the bridge adjustable while you cross it: - `configureCompat({ ... })`, imported from `vue`, changes the global compat configuration — for example setting a feature ID to `false` to adopt Vue 3 behaviour app-wide, or to `'suppress-warning'` to hide known debt; - a component's `compatConfig` option applies the same settings to one component, so converted components can opt into Vue 3 behaviour while the rest of the app stays in Vue 2 mode.

  • Why can a production build of an app on @vue/compat look clean even though plenty of Vue 2 usage remains?
    The deprecation warnings are development-only: the warning function returns immediately outside dev builds. Production keeps the Vue 2 behaviour but reports nothing, so the only reliable inventory comes from running the dev server and the test suite and collecting the `(deprecation ID)` messages.
  • What kind of dependency makes an app ineligible for the migration build, and what do you do about it?
    One that relies on Vue 2 internals or undocumented behaviour, most commonly private VNode properties. The build covers only documented public APIs and will not be tweaked to cover such cases. You wait for, upgrade to or replace with a Vue 3-compatible version before switching, or keep that dependency's part of the app on Vue 2 behaviour until you can.

saying these in an interview costs you the question

  • @vue/compat is a Vue 2 plugin that adds Vue 3 APIs to the old runtime.
  • The migration build starts in Vue 3 mode and you opt into Vue 2 features.
  • Aliasing vue to @vue/compat is enough; templates compile in Vue 2 mode automatically.
  • Every breaking change emits a warning, so a quiet console means the migration is done.
  • An app running on the migration build must never be shipped to production.
open as a page

What did Vue 2.7 backport from Vue 3, and why do teams upgrade a Vue 2.6 app to 2.7 before moving to Vue 3?

level: middleimportance: should knowfreq 38%

basics

~20 s

Vue 2.7, the final 2.x minor (July 2022), built in the Composition API, <script setup> and v-bind() in <style>, with emits for type inference only. Upgrading first lets new code take its Vue 3 shape while the runtime stays Vue 2.

open as a page

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?

level: seniorimportance: should knowfreq 34%

basics

~20 s

Make 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.

open as a page

You lead a large Vue 2.6 app with custom SSR, a Vue 2-only component library and many mixins; how would you plan and stage its move to Vue 3?

level: principalimportance: should knowfreq 30%

basics

~20 s

Audit eligibility first: dependencies on Vue 2 internals, IE11 and custom SSR block the migration build. Go to 2.7 for Vue 3-style new code, resolve the blockers, then ship on @vue/compat and move components to MODE 3 until it can go.

open as a page

In Vue's migration build, how do configureCompat() and a component's compatConfig option interact, and what do MODE 2, MODE 3 and 'suppress-warning' change?

level: seniorimportance: nice to knowfreq 22%

basics

~20 s

configureCompat() sets the global compat config; a component's compatConfig overrides it key by key. In MODE 2 a feature stays on unless set to false; in MODE 3 only features set to true or 'suppress-warning' (silent) stay on.

open as a page