Vue.jsのアプリケーションが重い。レンダリングのたびに仮想DOMの差分計算が走り、大量コンポーネントを抱えるページではパフォーマンスがボトルネックになる――そんな課題に正面から応えるのがVapor Modeです。

Vapor Modeは、Vue 3.6で導入される仮想DOMを完全にスキップする新しいコンパイルモードです。テンプレートからDOMを直接生成するため、差分計算のオーバーヘッドがゼロになり、SolidやSvelte 5と同水準のパフォーマンスを実現します。2026年2月時点でVue 3.6はベータ段階(最新 v3.6.0-beta.6)にあり、Vapor Modeの機能セットは完成済みです。

仮想DOMの仕組みとパフォーマンス上の課題

Vueは従来、 仮想DOM(Virtual DOM) を使ってUIを更新してきました。仮想DOMの処理フローは以下のとおりです。

  1. テンプレートをコンパイルしてrender関数を生成する
  2. render関数がVNode(仮想DOMツリー)を作成する
  3. 状態が変化すると新しいVNodeツリーを生成する
  4. 新旧VNodeの差分(diff)を計算する
  5. 差分を実DOMに反映(patch)する

この仕組みは「変更箇所だけを効率的に更新する」意図で設計されていますが、diffアルゴリズム自体にCPU・メモリコストがかかります。特に以下のケースで負荷が顕著になります。

  • 数百〜数千のコンポーネントを同時にレンダリングする画面
  • 高頻度で状態が更新されるリアルタイムダッシュボード
  • モバイル端末などリソースが限られた環境

Vue 3ではStatic Hoisting(静的ノードの巻き上げ)やPatch Flags(動的部分のマーキング)といった最適化が施されていますが、仮想DOMの差分計算という根本的なコストは残っています。

Vapor Modeの動作原理

Vapor Modeは仮想DOMを一切使わずにUIを更新します。コンパイラがテンプレートを解析し、DOM操作を行うJavaScriptコードを直接出力します。

従来の仮想DOMモード

テンプレート → render関数 → VNode生成 → diff計算 → DOM更新

Vapor Mode

テンプレート → コンパイル → DOM操作コード → 直接DOM更新

中間のVNode生成やdiff計算が不要なため、以下のメリットがあります。

比較項目仮想DOMモードVapor Mode
レンダリング方式VNode差分比較直接DOM操作
ランタイムサイズ約16〜27KB(gzip)約10KB未満
diff計算コスト毎回発生なし
メモリ使用量VNodeツリー保持最小限
SolidやSvelte 5との性能比較やや劣る同等水準

Vapor Modeは完全にオプトインの仕組みです。既存のコードを壊すことなく、必要なコンポーネントだけをVapor化できます。

Vue 3.6の現在のステータス

Vue 3.6はVapor Modeを含むメジャーアップデートです。2026年2月時点でのリリース状況は以下のとおりです。

バージョンリリース日備考
v3.6.0-alpha.72025年12月12日alpha最終版
v3.6.0-beta.12025年12月23日Vapor Mode機能セット完成
v3.6.0-beta.62026年2月12日最新ベータ版

出典: GitHub vuejs/core Releases

安定版のリリース日は未発表ですが、ベータ段階でバグ修正が進んでいるため、2026年前半の正式リリースが見込まれます。Vapor Modeはベータ段階でも試用可能です。

Vapor Modeの有効化と2つの利用パターン

パターン1: 部分的にVaporコンポーネントを使う(ハイブリッド)

既存の仮想DOMアプリケーション内で、パフォーマンスが重要な一部のコンポーネントだけをVapor化する方法です。アプリ全体は従来どおりcreateAppで作成し、vaporInteropPluginを登録した上で、特定のSFCにvapor属性を付与します。

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

createApp(App).use(vaporInteropPlugin).mount('#app')
<!-- CounterVapor.vueVaporコンポーネント -->
<script setup vapor>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <button @click="count++">カウント: {{ count }}</button>
</template>
<!-- App.vue通常の仮想DOMコンポーネント -->
<script setup>
import CounterVapor from './CounterVapor.vue'
</script>

<template>
  <h1>アプリケーション</h1>
  <CounterVapor />
</template>

ポイントは2つです。vaporInteropPluginをアプリに登録することで、仮想DOMとVaporコンポーネントの相互運用が可能になります。そして<script setup vapor>vapor属性を付けるだけで、そのコンポーネントはVapor Modeでコンパイルされます。VaporとVDOMのコンポーネントは双方向にネストできます。

パターン2: アプリ全体をVapor Modeにする

新規プロジェクトでアプリ全体をVapor Modeで構築する場合は、createVaporAppを使います。

// main.ts
import { createVaporApp } from 'vue'
import App from './App.vue'

createVaporApp(App).mount('#app')

createVaporAppで起動すると、仮想DOMのランタイムコードがバンドルに含まれなくなり、ベースラインのバンドルサイズが大幅に縮小します。

alien-signals: リアクティビティシステムの刷新

Vue 3.6では、リアクティビティの基盤である@vue/reactivityパッケージがalien-signalsをベースに全面リファクタリングされました。

alien-signalsの概要

alien-signalsはJohnson Chu氏が開発したシグナルライブラリです。push-pullベースのシグナルアルゴリズムを採用し、Array・Set・Mapを一切使わないフラグベースの状態管理で極限まで最適化されています。Vue 3.6のリアクティビティエンジンとして採用されました(PR #12349)。

出典: GitHub stackblitz/alien-signals

従来のリアクティビティとの性能差

指標Vue 3.4以前Vue 3.6(alien-signals)
リアクティビティ全体性能基準値約400%向上
メモリ使用量基準値約14%削減
計算エフェクト標準大幅最適化

alien-signalsの恩恵はVapor Modeだけでなく、従来の仮想DOMモードでも受けられます。refcomputedwatchの内部動作が高速化されるため、Vue 3.6にアップグレードするだけでアプリケーション全体のリアクティビティ性能が向上します。

defineVaporComponentによるコンポーネント定義

SFC以外でVaporコンポーネントを定義する場合、defineVaporComponentを使います。特にJSXでVapor Modeを利用する際に有用です。

import { defineVaporComponent } from 'vue'

export default defineVaporComponent(({ name }: { name: string }) => {
  return <p>Hello, {name}!</p>
})

defineVaporComponentはpropsの分割代入をサポートし、リアクティビティを保ちながらReactライクな関数コンポーネントの書き方を実現します。通常の関数コンポーネントではpropsを分割代入するとリアクティビティが失われるため、分割代入が必要な場合はdefineVaporComponentを使用してください。

vue-jsx-vapor: JSXでVapor Modeを使う

vue-jsx-vaporは、Vue JSXでVapor Modeを利用するためのコンパイラ&ビルドツールプラグインです。zhiyuanzmj氏が中心となって開発しており、Vue公式organizationの配下で管理されています。

出典: GitHub vuejs/vue-jsx-vapor

主な特長

  • Oxc(Rust製パーサー)でコンパイル: Babelベースの従来実装と比較して約20倍の処理速度
  • 仮想DOMとVapor DOMの両方を生成可能: v3.1からInterop対応
  • Vue組み込みディレクティブをJSXで利用可能: v-modelv-showv-ifなど
  • defineStyleマクロ: JSXファイル内でスコープ付きCSSを定義可能
  • 型安全性: Volar+TS Macroプラグインによる型チェック対応

コード例

import { ref } from 'vue'

export default function Counter() {
  const count = ref(0)

  return <button onClick={() => count.value++}>{count.value}</button>
}

従来のVue JSXではdefineComponentでラップしrender関数を返す二重構造が必要でしたが、vue-jsx-vaporではJSXを直接返すだけで動作します。

パフォーマンスベンチマーク

公式および第三者ベンチマークによると、Vapor Modeは既存のVue仮想DOMモードと比較して顕著なパフォーマンス向上を示しています。

ベンチマーク項目Vue 3.5(仮想DOM)Vue 3.6 Vapor Mode参考: Solid.js
ランタイムサイズ(gzip)約16〜27KB約10KB未満約7KB
大量コンポーネントマウント(10万件)数百ms約100ms同等
メモリ使用量基準値約14%削減同等水準

出典: Vue.js Nation 2025 Evan Youプレビュー

Vapor Modeは第三者ベンチマークでSolidやSvelte 5と同等のパフォーマンスを達成しています。仮想DOMのdiffコストがなくなることで、特に大量のDOM更新が発生するユースケースで大きな差が生まれます。

Nuxt.jsでのVapor Mode対応

NuxtチームもVapor Modeへの対応を進めています。Nuxt 4はすでにリリースされていますが、Vapor Modeの公式統合はまだ実現していません。Vue本体のVaporが安定版に到達した段階でNuxt側の対応が本格化する見込みです。

2026年2月時点では、Nuxtアプリケーション内でVapor Modeを利用するには、Vue 3.6のSFCで<script setup vapor>を使って個別のコンポーネントをVapor化する方法が現実的です。Nuxt公式のフルサポートを期待する場合は、今後のアナウンスを待つことを推奨します。

Vapor Modeの制約と未対応機能

Vapor Modeは強力ですが、現在のベータ段階ではいくつかの制約があります。

機能対応状況
Composition API(<script setup>対応済み
ref / reactive / computed / watch対応済み
v-if / v-for / v-model / v-show対応済み
<Teleport> / <KeepAlive> / <Transition>対応済み
Options API非対応
getCurrentInstance()非対応
カスタムディレクティブ異なるインターフェースで対応
app.config.globalProperties非対応
要素ライフサイクルイベント(@vue:xxx非対応
Suspense(Vapor単体)非対応(VDOMのSuspense内にVaporコンポーネントを配置は可能)

Options APIを使用している既存コンポーネントをVapor化するには、事前にComposition APIへの書き換えが必要です。

既存プロジェクトへの段階的導入ステップ

Vapor Modeは全か無かの選択ではなく、段階的に導入できます。以下の手順が現実的です。

Step 1: Vue 3.6にアップグレードする

npm install vue@3.6.0-beta.6

まずVue本体を3.6系に更新します。この時点ではVapor Modeを使わなくても、alien-signalsによるリアクティビティの高速化が適用されます。

Step 2: パフォーマンスボトルネックのコンポーネントを特定する

Vue DevToolsやブラウザのPerformanceタブでレンダリングに時間がかかっているコンポーネントを特定します。

Step 3: 対象コンポーネントにvapor属性を付与する

<!-- 変更前 -->
<script setup>
// ...
</script>

<!-- 変更後 -->
<script setup vapor>
// ...
</script>

<script setup vapor>を追加するだけでコンパイルモードが切り替わります。Options APIを使用している場合はComposition APIへの書き換えが先に必要です。

Step 4: 動作確認とベンチマーク計測

Vaporコンポーネントが正しく動作するかテストし、パフォーマンス改善を計測します。

まとめ

Vapor ModeはVue.jsが仮想DOMの制約を超えて、SolidやSvelte 5と同等のレンダリング性能を手に入れるための重要な進化です。<script setup vapor>と書くだけで有効化でき、既存プロジェクトにも段階的に導入できる設計になっています。

Vue 3.6はベータ段階ですが、Vapor Modeの機能セットは完成しており、安定版リリースに向けてバグ修正が進んでいます。Vapor Modeの開発は当初vuejs/vue-vaporで行われていましたが、2025年7月にvuejs/core本体に統合されました。最新の進捗はVue公式のGitHubリリースページで確認できます。

Vapor Modeを試すための公式ツールも用意されています。

JSXでVapor Modeを使いたい場合はvue-jsx-vaporも確認してみてください。