3.6.0-beta.9 (2026-03-26)
- compiler-vapor: avoid delegating same-event handlers when sibling uses
stopmodifiers (#14610) (bf7a066), closes #14609 - compiler-vapor: handle template children in Transition (#14606) (5fb8b33)
- compiler-vapor: ignore comments when checking extraneous default slot children (#14601) (5af41dd)
- compiler-vapor: normalize default dynamic slot names in transform (#14619) (c615e05)
- compiler-vapor: preserve comment-only default slots while ignoring mixed slot comments (#14604) (c245dae)
- hydration: align vapor teleport null-target fallback with vdom (5d6814f), closes #14586
- hydration: avoid setting targetStart to placeholder when target is null (#14589) (5f38d73)
- hydration: consume target anchors for disabled teleports (#14592) (a0ba73b)
- hydration: handle enabled teleport hydration with null target (#14586) (715b40f)
- hydration: handle nested disabled teleport anchor location (#14587) (befc127)
- hydration: pass nextSibling to locateTeleportEndAnchor for null target (abe8fcd)
- keep-alive: avoid allocating composite keys on cache lookup (981bd83)
- keep-alive: fix keyed branch scope leak in KeepAlive (cbe905e)
- keep-alive: handle KeepAlive teardown for keyed live branches (340ef37)
- keep-alive: prevent stale cacheBlock() calls when VDOM async component resolves after being unmounted or witched (3b2ffb7)
- keep-alive: support VDOM async components in VaporKeepAlive (6123f9b)
- runtime-vapor: align KeepAlive interop directives with non-element root bailout (1a91660)
- runtime-vapor: clean up keptAliveScopes in pruneCacheEntry (2e78d1e)
- runtime-vapor: clear template ref when switching to unresolved async component (e09b67a)
- runtime-vapor: clear template refs on KeepAlive deactivation (4c5a620)
- runtime-vapor: delay teleport child init until target is available (#14593) (3941eab)
- runtime-vapor: ensure KeepAlive onBeforeUnmount cleans up all cached entries (d978639)
- runtime-vapor: fix compositeKeyCachePrimitive memory leak in KeepAlive (16c071c)
- runtime-vapor: fix keptAliveScopes key mismatch causing scope leak on prune (3f2603d)
- runtime-vapor: handle async component names in KeepAlive pruneCache (b210f01)
- runtime-vapor: handle KeepAlive template ref cleanup for async branches (5239691)
- runtime-vapor: invalidate pending mount hooks on deactivate/unmount (0d8c519)
- runtime-vapor: invoke directive update hooks on KeepAlive reactivation (a2e32e0)
- runtime-vapor: invoke onVnodeBeforeMount for vapor components in interop (68c405c)
- runtime-vapor: invoke vnode lifecycle hooks in vdom interop (b7c9fc2)
- runtime-vapor: invoke vnode update hooks on KeepAlive reactivation (446b21b)
- runtime-vapor: preserve async wrapper keys across dynamic fragment updates (fea9fd9)
- runtime-vapor: preserve KeepAlive keyed scope cache for falsy keys (f0c9478)
- runtime-vapor: prune KeepAlive composite cache keys (e2cf58a)
- runtime-vapor: restore render context for interop slot fallbacks (#14596) (f6952b2)
- runtime-vapor: reuse teleport anchors when keyed roots reorder (#14591) (df8e1eb)
- runtime-vapor: TransitionGroup with v-for + v-if not applying transition hooks (#14590) (1916785)
- runtime-vapor: update props/slots on vapor child reactivation in vdom KeepAlive (ed276a9)
- teleport: clean up old anchors when teleport target changes (#14588) (d614897)
- teleport: ensure target anchor is removed only if it exists (b671f4b)
- teleport: handle missing slots edge case (#14597) (e79b814)
- teleport: reapply teleport css vars after root replacement (#14594) (caea24d)
- teleport: remove stale target anchors after invalid target updates (#14600) (e7828d4)
- teleport: should not mount deferred teleport after unmount (#14598) (e473e23)
- transition-group: align key inheritance with vdom (bb63124)
- transition-group: align transition-group dynamic tag updates with vdom (5348391)
- transition-group: avoid invalid hooks on unkeyed interop children (82c1223)
- transition-group: handle v-if dynamic slots (#14628) (9ac929a)
- transition-group: support vdom children with comment roots (9830c4a)
- transition: align interop transition vnode identity with vdom (efda719)
- transition: isolate transition leaving cache by resolved child type (cc0d96f)
- transition: treat null transition keys as absent in child fallback (724fd88)
- vdomInterop: keep interop fragment nodes in sync after vnode updates (c62dc1f)
- vdomInterop: keep vdom slot fragment nodes in sync with child updates (26e4a81)
- vapor: preserve static keys (62cb2ce)
3.6.0-beta.8 (2026-03-16)
- compiler-vapor: avoid cache name collisions in expression dedupe (#14568) (9101686)
- compiler-vapor: do not cache expressions with globally allowed identifiers (#14562) (cc2f3f5), closes #14560
- compiler-vapor: fix circular reference in repeated call expression cache (#14567) (62f2ab4)
- compiler-vapor: preserve :is prop on normal components (#14491) (c763388)
- custom-element: should properly patch as props for vapor custom elements (#14583) (c4b51d8), closes #12409
- hmr: child reload in dynamic branch should not break subsequent parent reload (#14527) (abefa0c)
- hmr: preserve appContext on root HMR reload (#14528) (714151e)
- runtime-vapor: cleanup stale refs when dynamic vdom component ref target changes (#14501) (178b77f)
- runtime-vapor: correct vapor slot props proxy has/ownKeys semantics (#14522) (8a64a19)
- runtime-vapor: enable hydration capability for createSSRApp + vdomInterop (#14505) (5c320b7)
- runtime-vapor: ensure vapor slot unmounting removes vnode slot content (#14520) (eff4cab)
- runtime-vapor: fix interop hydration anchor handling for Teleport/Suspense dynamic VNodes (#14517) (7d079d5)
- runtime-vapor: fix VDOM interop hydration for multi-node vnode ranges (#14513) (6a53e41)
- runtime-vapor: handle null/undefined dynamic template refs without warning (#14502) (b7a3356)
- runtime-vapor: handle out-in transition with empty leaving branch (#14538) (70647b6)
- runtime-vapor: handle Static/Fragment vnode ranges in interop block nodes (#14510) (8ec6b64)
- runtime-vapor: handle transition in-out leave without incoming branch (#14535) (191a1e1), closes #14533
- runtime-vapor: hydrate vapor slot in vdom component with sibling nodes (#14512) (fe613c7)
- runtime-vapor: keep vdom child attrs in sync with vapor parent updates (#14521) (11cb112)
- runtime-vapor: pass parentComp to _injectChildStyle for correct style ordering (79190e8)
- runtime-vapor: properly resolve event handler in dynamic props (#14514) (6764170)
- runtime-vapor: properly set ref on dynamic component + vdom component (#14496) (e05c850)
- runtime-vapor: should not pass reserved props into vapor attrs on update (#14524) (91f1483)
- runtime-vapor: TransitionGroup with v-if + v-for not applying transition hooks (#14571) (508edbe), closes #14564 #14569
- transition: handle rapid in-out transition toggles (#14540) (452290d), closes #14539
- vapor: infer component multi-root metadata from SFC templates for hydration (#14530) (c531937)
3.6.0-beta.7 (2026-02-27)
- runtime-vapor: allow renderEffect to self re-queue on sync state mutation (#14477) (e0003aa)
- runtime-vapor: apply template ref on dynamic fragment (#14471) (2fb57c4)
- runtime-vapor: avoid exposing built-in components internals via template ref (#14448) (3badf50)
- runtime-vapor: preserve slot owner rendering context in resolveDynamicComponent (#14475) (a779531), closes #14474
- runtime-vapor: preserve slot-owner css vars for teleported slot content (#14476) (24f20e8), closes #14473
- runtime-vapor: restore KeepAlive branch key even for falsy previous values (4859f89)
- runtime-vapor: widen FunctionalVaporComponent props typing (#14470) (74645bb), closes #14467
- vapor: support rendering vdom suspense in vapor (#14485) (f0367b0)
- vapor: support rendering vdom teleport in vapor (#14484) (9923f11), closes #14481
3.6.0-beta.6 (2026-02-12)
- compiler-vapor: always keyed if fragment when the branch can change (9f7d73d)
- compiler-vapor: handle invalid table nesting with dynamic child (#14394) (cd00cb8), closes #14392
- compiler-vapor: keep literal interpolation in component slot templates (#14405) (c18e1e2)
- compiler-vapor: properly handling of class and style bindings on SVG (#14383) (3019448), closes #14382
- runtime-vapor: guard attrs proxy traps for symbol keys (#14447) (1219d7d)
- runtime-vapor: guard default slot for createPlainElement (#14422) (6a64941)
- runtime-vapor: isolate slotProps per fragment in v-for slots (#14406) (9db9f1e), closes #14397
- runtime-vapor: stabilize KeepAlive cache keys with branch-scoped composite keys (d207e9e)
- runtime-vapor: update setCurrentBranchKey to return previous key and handle context correctly (c9e52bc)
- teleport: ignore to prop changes while disabled (#14438) (102b32b)
- teleport: optimize props handling and prevent unnecessary updates (#14440) (90ea8ce), closes #14438
- templateRef: don't update setup ref for useTemplateRef key (#14444) (ccd1ddf)
- templateRef: avoid setting direct ref of useTemplateRef in dev (#14442) (78eb86c)
- compiler-vapor: add keyed block handling for dynamic keys (862ab17)
3.6.0-beta.5 (2026-01-30)
- runtime-vapor: preserve slot owner to ensure correct scopeId inheritance for nested components within v-for loops with slots. (#14353) (cb2a17c)
- transition: add key for transition if-branches (#14374) (e08308e), closes #14368
- vapor: properly move vapor component / slot (#14363) (b0c04eb)
- vapor: support directives on vapor components in vdom parent (#14355) (9add6d7)
3.6.0-beta.4 (2026-01-23)
- compile-vapor: optimize always close tag on rightmost (0db578b)
- compiler-vapor: allow multiple children in Transition v-if branch elements (#14317) (212bee4), closes #14316
- compiler-vapor: do not escape quotes in root-level text nodes (#14310) (3fc8e4a), closes #14309
- compiler-vapor: prevent end tag omission for scope boundary elements (3d550db)
- keep-alive: fix caching nested dynamic fragments (#14307) (bd9aa97)
- runtime-core: queue mounted hooks added during mount (#14349) (d3b1de3)
- runtime-dom: ensure css vars deps tracking when component has no DOM on mount (#14299) (084389e)
- runtime-vapor: handle component scopeid on nested slot (#14326) (7324791)
- runtime-vapor: prevent v-for crash on looping through null or undefined array (#14328) (e77b6e1)
- teleport: apply css vars after hydration (#14343) (b117d11)
- transition: handle transition on pre-resolved async components (#14314) (9d30aff)
- vapor: refined inline-block nesting check for html abbreviation (9220643)
3.6.0-beta.3 (2026-01-12)
- compiler-vapor: support
v-ifandv-foron the same<template>element by correctly wrapping structural directives. (#14289) (ea1c978) - keep-alive: improve KeepAlive caching behavior for async components by re-evaluating caching after resolution (#14285) (6fc638f)
- runtime-vapor: prevent event handler execution during emits lookup (#14281) (15f6652), closes #14218 #14280
- teleport: handle css var update on nested fragment (#14284) (9bb5046)
- runtime-vapor: allow VDOM components to directly invoke vapor slots via
slots.name()(#14273) (6ffd55a) - vapor: support rendering VNodes in dynamic components (#14278) (b074a81)
3.6.0-beta.2 (2026-01-04)
- compiler-sfc: avoid duplicated unref import for vapor mode (#14267) (f9e87ce), closes #14265
- compiler-vapor: avoid cache declarations for call expression member access (#14245) (cef372b), closes #14244
- compiler-vapor: cache optional call expression (#14246) (7a0cbc0)
- runtime-core: support
uidkey foruseInstanceOption(#14272) (55bdced), closes vuejs/rfcs#814 - runtime-vapor: correctly check slot existence in ownKeys (#14252) (1d376e0)
- runtime-vapor: handle css vars work with empty VaporFragment (#14268) (8aa3714), closes #14266
- templateRef: handling template ref on vdom child with insertion state (#14243) (cc872d6), closes #14242
3.6.0-beta.1 (2025-12-23)
Vue 3.6 is now entering beta phase as we have completed the intended feature set for Vapor Mode as outlined in the roadmap! Vapor Mode now has feature parity with all stable features in Virtual DOM mode. Suspense is not supported in Vapor-only mode, but you can render Vapor components inside a VDOM Suspense.
3.6 also includes a major refactor of @vue/reactivity based on alien-signals, which significantly improves the reactivity system's performance and memory usage.
For more details about Vapor Mode, see About Vapor Mode section at the end of this release note.
- compiler-vapor: camelize kebab-case component event handlers (#14211) (b205408)
- compiler-vapor: merge component v-model onUpdate handlers (#14229) (e6bff23)
- compiler-vapor: wrap handler values in functions for dynamic v-on (#14218) (1e3e1ef)
- hmr: suppress
provide()warning during HMR updates for mounted instances (#14195) (d823d6a) - keep-alive: preserve fragment's scope only if it include a component that should be cached (26b0b37)
- runtime-core: remove constructor props for defineComponent (#14223) (ad0a237)
- runtime-vapor: implement v-once caching for props and attrs (#14207) (be2b79d)
- runtime-vapor: optimize prop handling in VaporTransitionGroup using Proxy (0ceebeb)
- transition: move kept-alive node before v-show transition leave finishes (e393552)
- transition: optimize prop handling in VaporTransition using Proxy (b092624)
- transition: prevent unmounted block from being inserted after transition leave (f9a9fad)
Vapor Mode is a new compilation mode for Vue Single-File Components (SFC) with the goal of reducing baseline bundle size and improved performance. It is 100% opt-in, and supports a subset of existing Vue APIs with mostly identical behavior.
Vapor Mode has demonstrated the same level of performance with Solid and Svelte 5 in 3rd party benchmarks.
Vapor Mode is feature-complete in Vue 3.6 beta, but is still considered unstable. For now, we recommend using it for the following cases:
- Partial usage in existing apps, e.g. implementing a perf-sensitive sub page in Vapor Mode.
- Build small new apps entirely in Vapor Mode.
Vapor Mode only works for Single File Components using <script setup>. To opt-in, add the vapor attribute to <script setup>:
<script setup vapor>
// ...
</script>Vapor Mode components are usable in two scenarios:
-
Inside a Vapor app instance create via
createVaporApp. Apps created this way avoids pulling in the Virtual DOM runtime code and allows bundle baseline size to be drastically reduced. -
To use Vapor components in a VDOM app instance created via
createApp, thevaporInteropPluginmust be installed:import { createApp, vaporInteropPlugin } from "vue"; import App from "./App.vue"; createApp(App) .use(vaporInteropPlugin) // enable vapor interop .mount("#app");
A Vapor app instance can also install
vaporInteropPluginto allow vdom components to be used inside, but it will pull in the vdom runtime and offset the benefits of a smaller bundle.
When the interop plugin is installed, Vapor and non-Vapor components can be nested inside each other. This currently covers standard props, events, and slots usage, but does not yet account for all possible edge cases. For example, there will most likely still be rough edges when using a VDOM-based component library in Vapor Mode.
A know issue is that vapor slots cannot be rendered with slots.default() inside a VDOM component. renderSlot must be used instead. [Example]
This is expected to improve over time, but in general, we recommend having distinct "regions" in your app where it's one mode or another, and avoid mixed nesting as much as possible.
In the future, we may provide support tooling to enforce Vapor usage boundaries in codebases.
By design, Vapor Mode supports a subset of existing Vue features. For the supported subset, we aim to deliver the exact same behavior per API specifications. At the same time, this means there are some features that are explicitly not supported in Vapor Mode:
- Options API
app.config.globalPropertiesgetCurrentInstance()returnsnullin Vapor components@vue:xxxper-element lifecycle events
Custom directives in Vapor also have a different interface:
type VaporDirective = (
node: Element | VaporComponentInstance,
value?: () => any,
argument?: string,
modifiers?: DirectiveModifiers,
) => (() => void) | void;value is a reactive getter that returns the binding value. The user can set up reactive effects using watchEffect (auto released when component unmounts), and can optionally return a cleanup function. Example:
const MyDirective = (el, source) => {
watchEffect(() => {
el.textContent = source();
});
return () => console.log("cleanup");
};Vapor Mode attempts to match VDOM Mode behavior as much as possible, but there could still be minor behavior inconsistencies in edge cases due to how fundamentally different the two rendering modes are. In general, we do not consider a minor inconsistency to be breaking change unless the behavior has previously been documented.
3.6.0-alpha.7 (2025-12-12)
- hmr: handle reload for template-only components switching between vapor and vdom (bfd4f18)
- hmr: refactor scope cleanup to use reset method for stale effects management (918b50f)
- hmr: track original
__vaporstate during component mode switching (#14187) (158e706) - runtime-vapor: enable injection from VDOM parent to slotted Vapor child (#14167) (2f0676f)
- runtime-vapor: track and restore slot owner context for DynamicFragment rendering (#14193) (79aa9db), closes #14192
- runtime-vapor: use computed to cache the result of dynamic slot function to avoid redundant calls. (#14176) (92c2d8c)
- runtime-vapor: implement
defineVaporCustomElementtype inference (#14183) (6de8f68) - runtime-vapor: implement
defineVaporComponenttype inference (#13831) (9d9efd4)
3.6.0-alpha.6 (2025-12-04)
- compiler-vapor: enhance v-slot prop destructuring support (#14165) (5db15cf)
- compiler-vapor: only apply v-on key modifiers to keyboard events (#14136) (8e83197)
- compiler-vapor: prevent
_camelizefrom receiving nullish value for dynamicv-bindkeys with.camelmodifier. (#14138) (313d172) - compiler-vapor: prevent nested components from inheriting parent slots (#14158) (0668ea3)
- compiler-vapor: support merging multiple event handlers on components (#14137) (f2152d2)
- KeepAlive: correct condition for caching inner blocks to handle null cases (71e2495)
- KeepAlive: remove unnecessary null check in getInnerBlock call (50602ec)
- runtime-vapor: add dev-only warning for non-existent property access during render (#14162) (9bef3be)
- runtime-vapor: expose raw setup state to devtools via
devtoolsRawSetupState(0ab7e1b) - templateRef: prevent duplicate onScopeDispose registrations for dynamic template refs (#14161) (750e7cd)
- TransitionGroup: simplify dev-only warning condition for unkeyed children (e70ca5d)
- runtime-vapor: support attrs fallthrough (#14144) (53ab5d5)
- runtime-vapor: support custom directives on vapor components (#14143) (e405557)
- suspense: support rendering of Vapor components (#14157) (0dcc98f)
- vapor: implement
v-oncesupport for slot outlets (#14141) (498ce69)
3.6.0-alpha.5 (2025-11-25)
- compiler-vapor: handle
TSNonNullExpressionand improve expression processing (#14097) (092c73a) - compiler-vapor: improve expression caching for shared member roots (#14132) (25ec4f4)
- compiler-vapor: prevent duplicate processing of member expressions in expression analysis (#14105) (35d135e)
- runtime-vapor: prevent infinite recursion in
vShow'ssetDisplaywhen handling Vapor components. (005ba04) - vapor: more accurate fallthrough attr support (#13972) (584f25f)
- runtime-vapor: prevent fragment
updatedhooks from running before the fragment is mounted. (#14123) (b07fa60)
3.6.0-alpha.4 (2025-11-14)
- compiler-vapor: handle boolean as constant node (#13994) (c1f2289)
- compiler-vapor: handle numbers as static text (#13957) (4b9399a)
- compiler-vapor: wrap event handler in parentheses for TSExpression (#14061) (0f4edb4)
- runtime-dom: useCssModule vapor support (#13711) (abe8fc2)
- runtime-vapor: force defer mount when teleport has insertion state (#14049) (b005811)
- runtime-vapor: preserve correct parent instance for slotted content (#14095) (fe3a998)
- transition-group: support reusable transition group (#14077) (171f3f5)
- vapor: v-model and v-model:model co-usage (#13070) (bf2d2b2)
- compiler-vapor: handle asset imports (#13630) (7d4ab91)
- vapor: implement defineVaporCustomElement (#14017) (615db5e)
- runtime-vapor: dynamic component fallback work with dynamic slots (#14064) (f4b3613)
- vapor: support svg and MathML (#13703) (f0d0cfd)
- vapor: dom event error handling (#13769) (d2eebe4)
3.6.0-alpha.3 (2025-11-06)
- compiler-vapor: adjust children generation order for hydration (#13729) (248b394)
- compiler-vapor: escape html for safer template output (#13919) (3c31b71)
- compiler-vapor: treat template v-for with single component child as component (#13914) (3b5e13c)
- hmr: properly stop render effects during hmr re-render (#14023) (34c6ebf)
- runtime-vapor: sync parent component block reference during HMR reload (#13866) (b65a6b8)
- runtime-vapor: apply v-show to vdom child (#13767) (def21b6), closes #13765
- runtime-vapor: fix readonly warning when useTemplateRef has same variable name as template ref (#13672) (e56997f), closes #13665
- runtime-vapor: handle vapor attrs fallthrough to vdom component (#13551) (5ce227b)
- runtime-vapor: pass plain object props to createVNode during vdom interop (#13382) (6c50e20), closes #14027
- runtime-vapor: properly handle consecutive prepend operations with insertionState (#13558) (6a801de), closes #13764
- runtime-vapor: properly handle fast remove in keyed diff (07fd7e4)
- runtime-vapor: remove v-cloak and add data-v-app after app mount (#14035) (172cb8b)
- runtime-vapor: resolve multiple vFor rendering issues (#13714) (348ffaf)
- runtime-vapor: setting innerHTML should go through trusted types (#13825) (23bc91c)
- runtime-vapor: setting innerHTML should go through trusted types (#14000) (a3453e3)
- runtime-vapor: avoid unnecessary block movement in renderList (#13722) (c4f41ee)
- runtime-core: handle next host node for vapor component (#13823) (96ca3b0), closes #13824
- compiler-vapor: support keys and nonKeys modifier for component event (#13053) (a697871)
- hydration: hydrate vapor async component (#14003) (1e1e13a)
- hydration: hydrate VaporTeleport (#14002) (a886dfc)
- hydration: hydrate VaporTransition (#14001) (f1fcada)
- runtime-vapor: add support for async components in VaporKeepAlive (#14040) (e4b147a)
- runtime-vapor: add support for v-once (#13459) (ff5a06c)
- runtime-vapor: add withVaporCtx helper to manage currentInstance context in slot blocks (#14007) (d381c2f)
- runtime-vapor: v-html and v-text work with component (#13496) (7870fc0)
- runtime-vapor: vapor transition work with vapor async component (#14053) (0f4d7fb)
- runtime-vapor: vapor transition work with vapor keep-alive (#14050) (c6bbc4a)
- runtime-vapor: vapor transition work with vapor teleport (#14047) (d14c5a2)
- vapor: defineVaporAsyncComponent (#13059) (6ec403f)
- vapor: forwarded slots (#13408) (2182e88)
- vapor: hydration (#13226) (d1d35cb)
- vapor: set scopeId (#14004) (5bdcd81)
- vapor: template ref vdom interop (#13323) (436eda7)
- vapor: vapor keepalive (#13186) (35475c0)
- vapor: vapor teleport (#13082) (7204cb6)
- vapor: vapor transition + transition-group (#12962) (bba328a)
3.6.0-alpha.2 (2025-07-18)
- compiler-vapor: handle empty interpolation (#13592) (d1f2915)
- compiler-vapor: handle special characters in cached variable names (#13626) (a5e106d)
- compiler-vapor: selectors was not initialized in time when the initial value of createFor source was not empty (#13642) (f04c9c3)
- reactivity: allow collect effects in EffectScope (#13657) (b9fb79a), closes #13656
- reactivity: remove link check to align with 3.5 (#13654) (3cb27d1), closes #13620
- runtime-core: use __vapor instead of vapor to identify Vapor components (#13652) (ad21b1b)
- runtime-vapor: component emits vdom interop (#13498) (d95fc18)
- runtime-vapor: handle v-model vdom interop error (#13643) (2be828a)
- runtime-vapor: remove access globalProperties warning (#13609) (fca74b0)
3.6.0-alpha.1 (2025-07-12)
-
Please see About Vapor Mode section below for details.
- reactivity: refactor reactivity core by porting alien-signals (#12349) (313dc61)
- css-vars: nullish v-bind in style should not lead to unexpected inheritance (#12461) (c85f1b5), closes #12434 #12439 #7474 #7475
- reactivity: ensure multiple effectScope
on()andoff()calls maintains correct active scope (#12641) (679cbdf) - reactivity: queuing effects in an array (#13078) (826550c)
- reactivity: toRefs should be allowed on plain objects (ac43b11)
- scheduler: improve error handling in job flushing (#13587) (94b2ddc)
- scheduler: recover nextTick from error in post flush cb (2bbb6d2)
Vapor Mode is a new compilation mode for Vue Single-File Components (SFC) with the goal of reducing baseline bundle size and improved performance. It is 100% opt-in, and supports a subset of existing Vue APIs with mostly identical behavior.
Vapor Mode has demonstrated the same level of performance with Solid and Svelte 5 in 3rd party benchmarks.
Vapor Mode is available starting in Vue 3.6 alpha. Please note it is still incomplete and unstable during the alpha phase. The current focus is making it available for wider stability and compatibility testing. For now, we recommend using it for the following cases:
- Partial usage in existing apps, e.g. implementing a perf-sensitive sub page in Vapor Mode.
- Build small new apps entirely in Vapor Mode.
We do not recommend migrating existing components to Vapor Mode yet.
Things that do not work in this version yet:
- SSR hydration* (which means it does not work with Nuxt yet)
- Async Component*
- Transition*
- KeepAlive*
- Suspense
Features marked with * have pending PRs which will be merged during the alpha phase.
Vapor Mode only works for Single File Components using <script setup>. To opt-in, add the vapor attribute to <script setup>:
<script setup vapor>
// ...
</script>Vapor Mode components are usable in two scenarios:
-
Inside a Vapor app instance create via
createVaporApp. Apps created this way avoids pulling in the Virtual DOM runtime code and allows bundle baseline size to be drastically reduced. -
To use Vapor components in a VDOM app instance created via
createApp, thevaporInteropPluginmust be installed:import { createApp, vaporInteropPlugin } from "vue"; import App from "./App.vue"; createApp(App) .use(vaporInteropPlugin) // enable vapor interop .mount("#app");
A Vapor app instance can also install
vaporInteropPluginto allow vdom components to be used inside, but it will pull in the vdom runtime and offset the benefits of a smaller bundle.
When the interop plugin is installed, Vapor and non-Vapor components can be nested inside each other. This currently covers standard props, events, and slots usage, but does not yet account for all possible edge cases. For example, there will most likely still be rough edges when using a VDOM-based component library in Vapor Mode.
This is expected to improve over time, but in general, we recommend having distinct "regions" in your app where it's one mode or another, and avoid mixed nesting as much as possible.
In the future, we may provide support tooling to enforce Vapor usage boundaries in codebases.
By design, Vapor Mode supports a subset of existing Vue features. For the supported subset, we aim to deliver the exact same behavior per API specifications. At the same time, this means there are some features that are explicitly not supported in Vapor Mode:
- Options API
app.config.globalPropertiesgetCurrentInstance()returnsnullin Vapor components- Implicit instance properties like
$slotsand$propsare not available in Vapor template expressions @vue:xxxper-element lifecycle events
Custom directives in Vapor also have a different interface:
type VaporDirective = (
node: Element | VaporComponentInstance,
value?: () => any,
argument?: string,
modifiers?: DirectiveModifiers,
) => (() => void) | void;value is a reactive getter that returns the binding value. The user can set up reactive effects using watchEffect (auto released when component unmounts), and can optionally return a cleanup function. Example:
const MyDirective = (el, source) => {
watchEffect(() => {
el.textContent = source();
});
return () => console.log("cleanup");
};Vapor Mode attempts to match VDOM Mode behavior as much as possible, but there could still be minor behavior inconsistencies in edge cases due to how fundamentally different the two rendering modes are. In general, we do not consider a minor inconsistency to be breaking change unless the behavior has previously been documented.
See 3.5 changelog
See 3.4 changelog
See 3.3 changelog
See 3.2 changelog
See 3.1 changelog
See 3.0 changelog