Vue 3.6 beta shipped with Vapor Mode feature-complete, and the pitch is almost comically simple: add vapor to your <script setup> tag and the compiler bypasses the virtual DOM entirely. No new syntax. No different template language. Just a single keyword that tells the build step to emit raw DOM operations instead of VNode diffing. After years of the framework world treating the VDOM as a necessary abstraction, Vue is quietly letting you opt out of it — one component at a time.

What the Compiler Does Differently

In standard Vue, your template compiles to a render function that produces a VNode tree. Every state change triggers a diff against the previous tree, and the framework patches the real DOM with the delta. It works, and the optimized template compiler already makes it fast. But you're still paying for that intermediate representation on every update cycle — memory for the tree, CPU for the comparison, garbage collection for discarded nodes.

Vapor Mode rewires this pipeline. The compiler analyzes your template at build time, identifies every reactive binding, and generates code that updates the exact DOM node when its underlying ref changes. No tree construction. No diffing. No patching phase.

The syntax stays familiar:

<script setup vapor>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>

That vapor keyword is the entire migration step for a component. The compiler handles the rest — conditionals, loops, event handlers, all hard-wired into direct DOM manipulations during the build. You write the same Vue you've always written; the output is fundamentally different.

The Benchmarks

Evan You's team reported numbers matching Solid and Svelte 5 in third-party benchmarks — frameworks designed as compiler-first from the start. The standout figures: roughly 100,000 components mounted in 100ms, about 25% faster than standard Vue rendering, and around 30% faster than React's current reconciler. Test applications saw First Contentful Paint drop from 1.2 seconds to 0.7 seconds.

The reactivity system also got a full rewrite in this release, swapping its internals for an implementation based on alien-signals. That alone cuts memory usage and improves tracking performance even without enabling the new rendering mode. The two changes compound nicely — faster reactivity feeding a leaner rendering pipeline.

What Won't Survive the Migration

Here's where optimism meets your existing codebase. The new mode only supports Composition API with <script setup>. If a component uses Options API — data(), methods, computed as object properties — it cannot run in this mode. Full stop.

The bigger concern is ecosystem compatibility. Vapor components don't produce VNodes at runtime, so any library that manipulates the VNode tree internally will break inside a Vapor boundary.

Works today Needs vaporInteropPlugin Not compatible yet
Custom composables Element Plus Render function components
Pinia stores Ant Design Vue getCurrentInstance()
Vue Router PrimeVue Options API components
VueUse utilities Headless UI app.config.globalProperties
Full TypeScript support Vuetify (partial) Per-element lifecycle hooks

The interop plugin bridges some gaps — it lets VDOM-based library components nest inside Vapor parents by falling back to the traditional renderer at the boundary. It's a compatibility shim, not a performance path, but it means you don't need every dependency to ship native support before you start converting your own code.

Mixed component trees work in both directions. A Vapor component renders inside a VDOM parent, and vice versa. There's overhead at each boundary crossing, so avoid ping-ponging between modes in tight render loops. For typical app architecture — a VDOM shell with Vapor leaf components — the cost is negligible.

Where to Start

Don't convert App.vue. Don't touch your layout components or your route wrappers. Start at the leaves.

The data table that renders 500 rows. The real-time dashboard widget refreshing every 200ms. The autocomplete dropdown filtering a thousand items on each keystroke. These are the components where VDOM overhead actually shows up in flame graphs, and they're the ones with the simplest dependency trees.

The migration sequence for a typical project:

  1. Upgrade to Vue 3.6 beta — pin the exact version

  2. Pick your heaviest leaf component

  3. Add vapor to its <script setup> tag

  4. Run your test suite — if it passes, profile the difference

  5. Work your way up the tree as libraries add native support

Stable release is projected for late 2026, with this becoming the recommended default sometime in 2027. The beta is usable today if you're comfortable running pre-release in non-critical paths. Most production teams should wait for the RC at minimum. But nothing stops you from benchmarking your worst-performing components right now — the conversion is literally one word.