---
title: "Vue 3.6 and Vapor Mode: where things stand · vuejs.school"
description: "Vue 3.6 is at its tenth release candidate and 3.5.43 is the stable release. What 3.6 brings, what the RCs changed, and what to do with your app now."
canonical_url: "https://vuejs.school/community/blog/vue-3-6-and-vapor-mode-where-things-stand"
meta:
  "og:description": "Vue 3.6 is at its tenth release candidate and 3.5.43 is the stable release. What 3.6 brings, what the RCs changed, and what to do with your app now."
  "og:image": "https://vuejs.school/_og/d/a_~VnVlIDMuNiBhbmQgVmFwb3IgTW9kZTogd2hlcmUgdGhpbmdzIHN0YW5kIMK3IHZ1ZWpzLnNjaG9vbA%2Cc_OgCard.takumi%2Ctitle_~VnVlIDMuNiBhbmQgVmFwb3IgTW9kZTogd2hlcmUgdGhpbmdzIHN0YW5k%2Cdescription_~VnVlIDMuNiBpcyBhdCBpdHMgdGVudGggcmVsZWFzZSBjYW5kaWRhdGUgYW5kIDMuNS40MyBpcyB0aGUgc3RhYmxlIHJlbGVhc2UuIFdoYXQgMy42IGJyaW5ncywgd2hhdCB0aGUgUkNzIGNoYW5nZWQsIGFuZCB3aGF0IHRvIGRvIHdpdGggeW91ciBhcHAgbm93Lg%2Ceyebrow_~UmVsZWFzZSBub3RlcyDCtyA3IG1pbiByZWFk%2Ctint_lilac%2Cp_Ii9jb21tdW5pdHkvYmxvZy92dWUtMy02LWFuZC12YXBvci1tb2RlLXdoZXJlLXRoaW5ncy1zdGFuZCI%2Cs_zLJl7Iz3JXEu7T-O.png"
  "og:image:alt": "Vue 3.6 and Vapor Mode: where things stand · vuejs.school"
  "og:image:height": "600"
  "og:image:type": image/png
  "og:image:width": "1200"
  "og:title": "Vue 3.6 and Vapor Mode: where things stand · vuejs.school"
  "twitter:image": "https://vuejs.school/_og/d/a_~VnVlIDMuNiBhbmQgVmFwb3IgTW9kZTogd2hlcmUgdGhpbmdzIHN0YW5kIMK3IHZ1ZWpzLnNjaG9vbA%2Cc_OgCard.takumi%2Ctitle_~VnVlIDMuNiBhbmQgVmFwb3IgTW9kZTogd2hlcmUgdGhpbmdzIHN0YW5k%2Cdescription_~VnVlIDMuNiBpcyBhdCBpdHMgdGVudGggcmVsZWFzZSBjYW5kaWRhdGUgYW5kIDMuNS40MyBpcyB0aGUgc3RhYmxlIHJlbGVhc2UuIFdoYXQgMy42IGJyaW5ncywgd2hhdCB0aGUgUkNzIGNoYW5nZWQsIGFuZCB3aGF0IHRvIGRvIHdpdGggeW91ciBhcHAgbm93Lg%2Ceyebrow_~UmVsZWFzZSBub3RlcyDCtyA3IG1pbiByZWFk%2Ctint_lilac%2Cp_Ii9jb21tdW5pdHkvYmxvZy92dWUtMy02LWFuZC12YXBvci1tb2RlLXdoZXJlLXRoaW5ncy1zdGFuZCI%2Cs_zLJl7Iz3JXEu7T-O.png"
  "twitter:image:alt": "Vue 3.6 and Vapor Mode: where things stand · vuejs.school"
---

> Index of every page on this site: [llms.txt](https://vuejs.school/llms.txt)

## Vapor Mode: opt in one component at a time

**Vapor Mode** is a second way to compile single-file components. A normal component compiles to a render function that builds a virtual DOM tree, which Vue compares with the previous tree to work out what to change. The Vapor compiler skips that tree and emits direct DOM operations, tied to the reactive values they read.

The rc.1 notes describe it as 100% opt-in, supporting a subset of Vue's APIs with mostly identical behaviour, with the goals of a smaller baseline bundle and better performance. You opt in per component with `<script setup vapor>`, its shorthand `<script vapor>`, or `<template vapor>` for template-only files.

In an existing app, Vapor components need the interop plugin, which lets Vapor and virtual DOM components nest inside each other:

*src/main.ts*

```
import { createApp, vaporInteropPlugin } from 'vue'
import App from './App.vue'

createApp(App).use(vaporInteropPlugin).mount('#app')
```

An app written entirely in Vapor can start with `createVaporApp(App)` instead and leave the virtual DOM runtime out of the bundle. The notes recommend two uses for now: a performance-sensitive page inside an existing app, or a small new app built fully in Vapor.

What Vapor components cannot use, per the rc.1 notes:

- the Options API
- `app.config.globalProperties`
- `getCurrentInstance()`, which returns `null`
- per-element `@vue:` lifecycle events
- `v-memo`
- properties such as `$el` and `$refs` on a template ref to a component

Two more things work differently. Custom directives use a new function-based interface: a directive receives the element and a getter for its value instead of a `binding` object, so directives written for virtual DOM components need rewriting. And calling `slots.default()` in a script runs the slot's rendering, which can create DOM nodes and reactive effects, so in Vapor it is not a safe way to inspect a slot; leave slot rendering to the template.

## The reactivity rewrite reaches every component

Vue 3.6 refactors `@vue/reactivity` on top of the [alien-signals](https://github.com/stackblitz/alien-signals) library, which the notes say significantly improves the performance and memory use of the reactivity system. It is not opt-in: every component in a 3.6 app runs on it, Vapor or not. That makes it the part most likely to surface a difference in an existing app.

## What the ten release candidates changed

The [changelog at rc.10](https://github.com/vuejs/core/blob/v3.6.0-rc.10/CHANGELOG.md) lists 266 entries for rc.2 to rc.10: 248 bug fixes, 17 performance improvements and one feature. Nearly all are filed under the Vapor compiler and runtime, and they cluster in the same places: hydration of server-rendered Vapor output, slots, `KeepAlive`, `Transition`, fallthrough attributes and the boundary between Vapor and virtual DOM components. The last two RCs were the largest, with 53 entries in rc.9 and 77 in rc.10.

One change was breaking: rc.2 made **event delegation opt-in**. Up to rc.1, Vapor attached eligible event listeners to `document` and dispatched from there. An ancestor calling `stopPropagation()` could therefore stop a child's handler from ever running, unlike normal Vue. Since rc.2, listeners attach to the element itself, as in virtual DOM mode, and delegation is a per-listener choice made with the `.delegate` modifier:

*src/components/RowList.vue*

```
<script setup vapor lang="ts">
defineProps<{ rows: { id: number; label: string }[] }>()
const emit = defineEmits<{ select: [id: number] }>()
</script>

<template>
  <ul>
    <li v-for="row in rows" :key="row.id">
      <button type="button" @click.delegate="emit('select', row.id)">{{ row.label }}</button>
    </li>
  </ul>
</template>
```

Here the buttons share one `click` listener on `document` instead of one listener each, and the `stopPropagation()` trade-off comes back for these handlers only. The modifier only exists in Vapor components and only applies to supported static events. The old `compilerOptions.eventDelegation` setting was removed; delete it if you set it while trying a beta or rc.1.

Other fixes bring Vapor closer to normal components. rc.9, for example, made a Vapor component's props shallow, so watching props is no longer deep, as in a virtual DOM component.

A few fixes reach beyond Vapor. rc.10 includes fixes in the shared reactivity and runtime code, such as notifying the rest of a batch when one subscriber throws, and keeping a local `useModel` value when the prop did not change. Those affect every component, so run your whole suite against the RC, not only the pages you convert.

## Which tools support Vapor so far

Three pieces of tooling have announced support in their own release notes:

- **Nuxt 4.6**, released on 5 October, supports Vapor in interop mode. You set `vue: { vapor: true }` in `nuxt.config.ts`, the app root stays on the virtual DOM, and pages or components opt in with the `vapor` attribute. It requires Vue `^3.6.0-rc.2` or newer, and the release post says routing, `useAsyncData`, layouts and most built-in components work without changes.
- **create-vue** has offered "Vue 3.6 (Release Candidate)" as an experimental option since version 3.23 in July. It sets every core Vue package to the `rc` tag through your package manager's overrides, so nothing pulls in a second copy of 3.5.
- **Vue (Official)**, the editor extension, listed support for Vapor directives in language tools 3.3.8, published on 22 July.

Component libraries are the open question. The rc.1 notes say interop covers standard props, events and slots but "does not yet account for all possible edge cases", and give a virtual DOM component library used inside Vapor as their example of where rough edges may remain. Their general advice applies: keep library components and Vapor components in separate regions of the app, and avoid nesting one mode inside the other as much as possible.

## What to run in production

The 3.5 line has kept moving. Three patches shipped during the RC phase: 3.5.41 on 5 August, 3.5.42 on 27 August and 3.5.43 on 17 September. They are bug fixes in hydration, `Suspense`, the SFC compiler and the shared runtime. 3.5.43, for example, fixes nested `Suspense` patches being dropped during hydration and keeps optional props optional when a runtime prop uses a generic `PropType`. Upgrading within 3.5 is a patch release with no API changes, so stay current:

```
npm install vue@3.5.43
```

Vue Router 5.4 arrived on 7 October with `useScrollRestoration` and `onRouteRendered`, plus a breaking change confined to its experimental API, which now normalises query values to arrays.

## Test 3.6 in a branch

Leave your main branch on 3.5.43 and install the RC in a new one. From the project root:

```
git switch -c try-vue-3-6
npm pkg set overrides.vue='$vue'
npm install vue@3.6.0-rc.10 --save-exact
```

What the last two lines do:

- `npm pkg set` adds `"overrides": { "vue": "$vue" }` to `package.json`. Pinia, Vue Router and `@vitejs/plugin-vue` declare the Vue versions they accept as ranges such as `^3.5.11`, and npm does not count a release candidate as inside such a range, so without the [override](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#overrides) npm stops with an `ERESOLVE` error, on this install or the next one. `$vue` stands for the version in your own dependencies; the single quotes stop the shell from reading it as a variable. pnpm and Yarn have their own override settings.
- `--save-exact` writes `3.6.0-rc.10` rather than `^3.6.0-rc.10`, so a later install cannot move you to a newer RC until you choose to.

Then, in that branch:

1. **Test without Vapor.** Run your full test suite and a manual pass of your main flows.
2. **Check the compatibility list.** Search your code for `getCurrentInstance`, `globalProperties`, `v-memo`, `@vue:` events, custom directives, and code that calls `slots.default()` to inspect a slot. Components that use them cannot become Vapor components as written.
3. **Convert one region.** Pick a page that is measurably slow, convert its components to `<script setup vapor>`, install `vaporInteropPlugin`, and measure again with a production build.
4. **Report what breaks.** Release candidates exist to find edge cases before a stable release. A minimal reproduction in an issue is the most useful thing a user can contribute at this stage.

If you start a small new app this week and can live with release candidate software, building it entirely in Vapor is one of the two uses the notes recommend. `npm create vue@latest` with the RC option sets the project up on the RC, but the generated `src/main.ts` still calls `createApp`: switch it to `createVaporApp` and add `vapor` to each component. If you add Vue Router, its `RouterView` and `RouterLink` are render-function components, which the notes say need `vaporInteropPlugin` even in a Vapor app; that brings the virtual DOM runtime back.

**Check it stuck**3 questions from the Performance and Vapor Mode quiz.

[**Practice now**](https://vuejs.school/learn/advanced/performance-and-vapor-mode?tab=quiz)

**Was this helpful?**

## **Keep reading**

[Deep dive · 7 min read**Vapor Mode, explained without the hype**](https://vuejs.school/community/blog/vapor-mode-explained-without-the-hype) [Tutorial · 7 min read**Vue warnings decoded: the ten you will meet first**](https://vuejs.school/community/blog/vue-warnings-decoded)

```json
{"@context":"https://schema.org","@graph":[{"@id":"https://vuejs.school/#website","@type":"WebSite","description":"A free AI-instructed school for Vue.js. Short tutorials, runnable code and quizzes that adapt to you.","name":"vuejs.school","url":"https://vuejs.school/","publisher":{"@id":"https://vuejs.school/#identity"}},{"@id":"https://vuejs.school/community/blog/vue-3-6-and-vapor-mode-where-things-stand#webpage","@type":"WebPage","dateModified":"2026-10-27T19:31:40.253Z","datePublished":"2026-10-08","description":"Vue 3.6 is at its tenth release candidate and 3.5.43 is the stable release. What 3.6 brings, what the RCs changed, and what to do with your app now.","name":"Vue 3.6 and Vapor Mode: where things stand","url":"https://vuejs.school/community/blog/vue-3-6-and-vapor-mode-where-things-stand","breadcrumb":{"@id":"https://vuejs.school/community/blog/vue-3-6-and-vapor-mode-where-things-stand#breadcrumb"},"isPartOf":{"@id":"https://vuejs.school/#website"},"potentialAction":[{"@type":"ReadAction","target":["https://vuejs.school/community/blog/vue-3-6-and-vapor-mode-where-things-stand"]}],"primaryImageOfPage":{"@id":"https://vuejs.school/#logo"}},{"@id":"https://vuejs.school/#identity","@type":"Organization","description":"A free AI-instructed school for Vue.js. Short tutorials, runnable code and quizzes that adapt to you.","name":"vuejs.school","url":"https://vuejs.school","logo":{"@id":"https://vuejs.school/#logo"}},{"@id":"https://vuejs.school/community/blog/vue-3-6-and-vapor-mode-where-things-stand#article","dateModified":"2026-10-27T19:31:40.253Z","datePublished":"2026-10-08","description":"Vue 3.6 is at its tenth release candidate and 3.5.43 is the stable release. What 3.6 brings, what the RCs changed, and what to do with your app now.","headline":"Vue 3.6 and Vapor Mode: where things stand","inLanguage":"en","isAccessibleForFree":true,"thumbnailUrl":"https://vuejs.school/_og/d/a_~VnVlIDMuNiBhbmQgVmFwb3IgTW9kZTogd2hlcmUgdGhpbmdzIHN0YW5kIMK3IHZ1ZWpzLnNjaG9vbA%2Cc_OgCard.takumi%2Ctitle_~VnVlIDMuNiBhbmQgVmFwb3IgTW9kZTogd2hlcmUgdGhpbmdzIHN0YW5k%2Cdescription_~VnVlIDMuNiBpcyBhdCBpdHMgdGVudGggcmVsZWFzZSBjYW5kaWRhdGUgYW5kIDMuNS40MyBpcyB0aGUgc3RhYmxlIHJlbGVhc2UuIFdoYXQgMy42IGJyaW5ncywgd2hhdCB0aGUgUkNzIGNoYW5nZWQsIGFuZCB3aGF0IHRvIGRvIHdpdGggeW91ciBhcHAgbm93Lg%2Ceyebrow_~UmVsZWFzZSBub3RlcyDCtyA3IG1pbiByZWFk%2Ctint_lilac%2Cp_Ii9jb21tdW5pdHkvYmxvZy92dWUtMy02LWFuZC12YXBvci1tb2RlLXdoZXJlLXRoaW5ncy1zdGFuZCI%2Cs_zLJl7Iz3JXEu7T-O.png","@type":["Article","BlogPosting"],"articleSection":["Release notes"],"author":{"@id":"https://vuejs.school/#identity"},"image":{"@id":"https://vuejs.school/#/schema/image/1"},"isPartOf":{"@id":"https://vuejs.school/community/blog/vue-3-6-and-vapor-mode-where-things-stand#webpage"},"mainEntityOfPage":{"@id":"https://vuejs.school/community/blog/vue-3-6-and-vapor-mode-where-things-stand#webpage"},"publisher":{"@id":"https://vuejs.school/#identity"}},{"@id":"https://vuejs.school/community/blog/vue-3-6-and-vapor-mode-where-things-stand#breadcrumb","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","name":"Blog","item":"https://vuejs.school/community/blog","position":1},{"@type":"ListItem","name":"Vue 3.6 and Vapor Mode: where things stand","position":2}]},{"@id":"https://vuejs.school/#logo","@type":"ImageObject","caption":"vuejs.school","contentUrl":"https://vuejs.school/apple-touch-icon.png","inLanguage":"en","url":"https://vuejs.school/apple-touch-icon.png"},{"@id":"https://vuejs.school/#/schema/image/1","@type":"ImageObject","contentUrl":"https://vuejs.school/_og/d/a_~VnVlIDMuNiBhbmQgVmFwb3IgTW9kZTogd2hlcmUgdGhpbmdzIHN0YW5kIMK3IHZ1ZWpzLnNjaG9vbA%2Cc_OgCard.takumi%2Ctitle_~VnVlIDMuNiBhbmQgVmFwb3IgTW9kZTogd2hlcmUgdGhpbmdzIHN0YW5k%2Cdescription_~VnVlIDMuNiBpcyBhdCBpdHMgdGVudGggcmVsZWFzZSBjYW5kaWRhdGUgYW5kIDMuNS40MyBpcyB0aGUgc3RhYmxlIHJlbGVhc2UuIFdoYXQgMy42IGJyaW5ncywgd2hhdCB0aGUgUkNzIGNoYW5nZWQsIGFuZCB3aGF0IHRvIGRvIHdpdGggeW91ciBhcHAgbm93Lg%2Ceyebrow_~UmVsZWFzZSBub3RlcyDCtyA3IG1pbiByZWFk%2Ctint_lilac%2Cp_Ii9jb21tdW5pdHkvYmxvZy92dWUtMy02LWFuZC12YXBvci1tb2RlLXdoZXJlLXRoaW5ncy1zdGFuZCI%2Cs_zLJl7Iz3JXEu7T-O.png","inLanguage":"en","url":"https://vuejs.school/_og/d/a_~VnVlIDMuNiBhbmQgVmFwb3IgTW9kZTogd2hlcmUgdGhpbmdzIHN0YW5kIMK3IHZ1ZWpzLnNjaG9vbA%2Cc_OgCard.takumi%2Ctitle_~VnVlIDMuNiBhbmQgVmFwb3IgTW9kZTogd2hlcmUgdGhpbmdzIHN0YW5k%2Cdescription_~VnVlIDMuNiBpcyBhdCBpdHMgdGVudGggcmVsZWFzZSBjYW5kaWRhdGUgYW5kIDMuNS40MyBpcyB0aGUgc3RhYmxlIHJlbGVhc2UuIFdoYXQgMy42IGJyaW5ncywgd2hhdCB0aGUgUkNzIGNoYW5nZWQsIGFuZCB3aGF0IHRvIGRvIHdpdGggeW91ciBhcHAgbm93Lg%2Ceyebrow_~UmVsZWFzZSBub3RlcyDCtyA3IG1pbiByZWFk%2Ctint_lilac%2Cp_Ii9jb21tdW5pdHkvYmxvZy92dWUtMy02LWFuZC12YXBvci1tb2RlLXdoZXJlLXRoaW5ncy1zdGFuZCI%2Cs_zLJl7Iz3JXEu7T-O.png"}]}
```