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?
answer
- global first, component overrides
- resolved one key at a time
- the mode sets the default
- on, but quiet
- compiler keys live in the build
basics
~20 sconfigureCompat() 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.
solid answer
~50 s`configureCompat({...})`, imported from `vue` (aliased to `@vue/compat`), edits the global config; a component's `compatConfig` option takes the same shape and, for every key it sets, wins over the global value — keys it does not set fall back to global. `MODE` decides the default: under `MODE: 2` a feature is on unless it is `false`; under `MODE: 3` it is off unless it is `true` or `'suppress-warning'`. `'suppress-warning'` keeps the Vue 2 behaviour and silences its warning. That lets you migrate component by component: `compatConfig: { MODE: 3 }` on a converted component, or `{ COMPONENT_V_MODEL: false }` on one that adopted the new `v-model` contract, while the rest stays in Vue 2 mode. `COMPILER_*` keys must go in the build's `compilerOptions.compatConfig`, because SFC templates are compiled before any runtime call. `OPTIONS_DATA_MERGE` can only be configured globally.
code
ts · 12 lines// main.ts, with vue aliased to @vue/compat
import { configureCompat } from 'vue'
// Stage 1: Vue 2 behaviour by default, known debt silenced
configureCompat({
MODE: 2,
WATCH_ARRAY: 'suppress-warning',
INSTANCE_EVENT_EMITTER: 'suppress-warning'
})
// Stage 3 (later): Vue 3 by default, only named leftovers kept
// configureCompat({ MODE: 3, INSTANCE_EVENT_EMITTER: true })go deeper
Recall that the migration build is configured globally with configureCompat() and per component with a compatConfig option, and that MODE 2 means Vue 2 behaviour.
Explain per-key resolution between component and global config, and how MODE flips the meaning of an unset feature. Know what true, false and 'suppress-warning' each do.
Use per-component MODE 3 or single-feature opt-outs to migrate mutually exclusive features such as render functions and component v-model, and flip features off only after their warnings disappear.
Design the configuration as a staged rollout: which debt is silenced and tracked, when the global default moves to MODE 3, and what evidence allows removing the alias.
## Two levels of configuration The migration build (`@vue/compat`) decides, for each **deprecation ID** such as `WATCH_ARRAY`, `RENDER_FUNCTION` or `COMPONENT_V_MODEL`, whether to keep the Vue 2 behaviour. That decision reads two configuration objects: - **global** — changed with `configureCompat({ ... })`, which you import from `vue` because the bundler aliases `vue` to `@vue/compat`; - **per component** — a `compatConfig` option on the component definition, with the same shape. Resolution happens **one key at a time**: if the component's `compatConfig` contains the key, its value is used; otherwise the global value is. A component that sets only `MODE` therefore still inherits any feature keys set globally. ## MODE sets the default `MODE` is itself a key, resolved the same way, and it defines what an unmentioned feature means. The global default is `MODE: 2`. | feature value | under `MODE: 2` | under `MODE: 3` | |---|---|---| | not set | Vue 2 behaviour, warns | Vue 3 behaviour | | `true` | Vue 2 behaviour, warns | Vue 2 behaviour, warns | | `'suppress-warning'` | Vue 2 behaviour, silent | Vue 2 behaviour, silent | | `false` | Vue 3 behaviour | Vue 3 behaviour | Two consequences: - `'suppress-warning'` is the tool for **accepted debt** — a feature you will not fix yet and do not want flooding the console; - `MODE` also accepts a **function** that receives the component definition and returns `2` or `3`, so a rule can decide per component without editing every file. ## Migrating component by component Some features cannot be satisfied for both versions at once: the render function API and the component `v-model` contract have mutually exclusive Vue 2 and Vue 3 behaviour. The per-component config lets one component move ahead: ```js export default { compatConfig: { MODE: 3 }, // this component now behaves as Vue 3 props: ['modelValue'], emits: ['update:modelValue'] } ``` or, more narrowly, `compatConfig: { COMPONENT_V_MODEL: false }` to switch only the `v-model` contract. The `COMPONENT_V_MODEL` warning itself suggests exactly this opt-in when it sees a component declaring a `modelValue` prop. The end game flips the global switch: `configureCompat({ MODE: 3, FEATURE_A: true })` makes Vue 3 the default and keeps only named leftovers on Vue 2 behaviour, until they are gone and the alias can be removed. ## What happens when you switch a feature off too early Switching a feature to `false` while code still depends on it fails in one of three ways, depending on how the build checks that feature: 1. **Soft-asserted features** — old usage still runs, but in development Vue logs the deprecation followed by a console error: `^ The above deprecation's compat behavior is disabled and will likely lead to runtime errors.` 2. **Hard-asserted features** — APIs removed entirely in Vue 3; the compat shim throws `<ID> compat has been disabled.` when the old API is called. 3. **Mutually exclusive features** such as `RENDER_FUNCTION` — these warn only while compat is **on**. Once off, Vue 3 semantics simply apply and nothing is logged, so an unconverted render function fails without any hint pointing at the setting. So a feature is switched off after its warnings are gone, not before — and for the third kind, after the code has been converted, because the warnings disappear the moment you flip it. ## Rules that trip people up - **`COMPILER_*` keys belong to the template compiler.** With a build setup, SFC templates are compiled at build time, so these keys go in the bundler's `compilerOptions.compatConfig`. Setting one through `configureCompat()` in a runtime-only build triggers a warning telling you to move it. - **The compiler's MODE defaults to 3**, separately from the runtime's default of 2 — the reason build configs pass `MODE: 2` explicitly. - **`OPTIONS_DATA_MERGE` is global-only**; setting it in a component's `compatConfig` produces a warning. - **Unknown keys** produce an `Invalid deprecation config` warning, which catches typos in feature IDs. - **Built-in components** such as `<Transition>` skip most compat checks for themselves; compat is aimed at your code and your dependencies. ## A worked rollout A typical sequence using only these two levers: 1. **Start** with the global default `MODE: 2` and no feature keys, and collect the warning IDs from dev and test runs. 2. **Silence deliberate debt** with `'suppress-warning'` — for example an event bus built on `$on` that will be replaced later — so new warnings stay visible. 3. **Convert components** one at a time; each one gets `compatConfig: { MODE: 3 }` or a single-feature opt-out when it is done, so a regression in a converted component shows up as a Vue 3 failure rather than being papered over by compat. 4. **Flip the global default** to `MODE: 3` once most components are converted, keeping only the named leftovers set to `true`. 5. **Remove the alias** when no key is left enabled and the app behaves the same on the standard build. Each step is reversible by changing configuration, which is what makes the migration build safe to ship between steps.
- A team sets `RENDER_FUNCTION: false` globally while old render functions still exist; what will they see?Probably nothing in the console. `RENDER_FUNCTION` has mutually exclusive Vue 2 and Vue 3 behaviour, and such features warn only while compat is on; once it is off, every render function gets Vue 3 semantics, so any still using the Vue 2 `h` signature just renders wrongly or throws. Convert render functions first, opting each component in with `compatConfig: { RENDER_FUNCTION: false }`.
- Why might you set `MODE` to a function instead of a number?A function receives each component definition and returns 2 or 3, so one global rule can put your converted components in Vue 3 mode and leave the rest, including third-party components you cannot edit, in Vue 2 mode — without adding `compatConfig` to every file.
saying these in an interview costs you the question
- A component's compatConfig replaces the whole global config for that component.
- 'suppress-warning' turns the Vue 2 behaviour off along with its warning.
- Under MODE 3, features stay on until you explicitly set them to false.
- COMPILER_ features can be toggled with configureCompat() in any build.
- OPTIONS_DATA_MERGE can be set per component like any other feature.