Skip to the solution
HardFrontend12 min read

What is Vapor mode in Vue 3.5+ and how does it differ from the virtual DOM?

1.1k views

The problem

Question presented to candidate: "You will hear people say 'Vue 3.5 has Vapor mode'. What is Vapor mode, is that version claim right, and how does rendering in Vapor differ from Vue's usual virtual DOM?"

What a strong answer should cover:

  • Vapor is an opt-in compilation mode for SFCs (<script setup vapor>): the compiler emits code that creates DOM from a template once and updates specific nodes inside reactive effects. No VNodes, no diff.
  • Version accuracy: Vapor is not in any stable release. Vue 3.5 is the current stable line; Vapor ships in the 3.6 release candidates (3.6.0-rc.12 at the time of writing).
  • Same reactivity system and same template syntax; what changes is the compiled output and the runtime it calls.
  • Virtual DOM recap: render produces a VNode tree, the renderer diffs it against the previous one, helped by patch flags and blocks.
  • How to use it: createVaporApp for an all-Vapor app, or vaporInteropPlugin to mix Vapor and VDOM components.
  • Limits: <script setup> and template-only SFCs only (no Options API), getCurrentInstance() returns null, v-memo is ignored.

Clarifying questions expected:

  • "Do you mean the concept, or whether we can use it in production today?"

Code / implementation expected: Optional β€” a <script setup vapor> component, and ideally a description of its compiled output.

  • vapor
  • performance
  • vue-3.5

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

12 min read Β· 11 sections

Read the code

VueA Vapor SFC (Vue 3.6 release candidate): one keyword opts the component in
<script setup vapor>
import { ref, computed } from "vue";
const count = ref(0);
const double = computed(() => count.value * 2);
</script>

<template>
  <section class="card">
    <h2>Vapor counter</h2>
    <p>Static paragraph that never changes.</p>
    <button @click="count++">count is {{ count }}</button>
    <p :class="{ even: count % 2 === 0 }">double: {{ double }}</p>
  </section>
</template>
Mounting Vapor: a pure Vapor app, or Vapor inside a virtual DOM app
// Option A: an app made only of Vapor components (no virtual DOM runtime is bundled)
// src/main.js
import { createVaporApp } from "vue"; import App from "./Counter.vue"; createVaporApp(App).mount("#app");

// Option B: Vapor components inside an existing virtual DOM app
// src/main.js
import { createApp, vaporInteropPlugin } from "vue"; import App from "./Counter.vue"; createApp(App).use(vaporInteropPlugin).mount("#app");

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 73 of 92 in Vue.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Vue.js questions
Up nextHard

What is effectScope?

Continue