記事一覧へ戻る
TRANSMISSION / MINT読了 18 分

Vue 3.6 RC アップグレード全解説—3.5 から Vapor Mode と alien-signals へ

Vue 3.6.0-rc.2 時点で、Vue 3.5 と 3.6 のリアクティビティコア、Vapor Mode、イベント委譲、相互運用境界、段階的な移行戦略を比較します。

#Vue#JavaScript#フロントエンド
Vue 3.5 の Virtual DOM コンポーネントツリーが結晶の通路を抜け、Vue 3.6 の細粒度シグナルネットワークへ移行する
Vue 3.6 RC は新 API の一覧というより、コンパイラとランタイムのアーキテクチャを切り替える更新です

バージョン番号だけを見れば、Vue 3.6 は普通のマイナーアップデートに見えます。しかしリリースノートを最後まで読むと、印象は違います。Vue が次の段階に向けてエンジンを交換する更新に近いのです。

一方では alien-signals を基盤にリアクティビティコアが再構築され、公開されている refcomputedwatch の使い方はほぼ変わりません。もう一方では Vapor Mode が正式に RC へ入り、Vue の SFC を Virtual DOM を経由せず、より直接的な DOM 更新ロジックへコンパイルできるようになります。

最初に、最も重要なバージョン情報を確認します。

2026 年 7 月 26 日時点で、Vue 3.6 の最新版は 3.6.0-rc.2 です。RC はリリース候補であり、安定版ではありません。この記事は評価、実験、移行準備のためのもので、すべての本番プロジェクトが直ちにアップグレードすべきだという意味ではありません。

先に結論:3.6 では何が変わったのか

比較項目Vue 3.5Vue 3.6 RC既存プロジェクトへの実際の影響
リアクティビティ3.5 で内部最適化済みalien-signals を基盤に大幅再構築通常の Composition API は書き直し不要ですが、複雑な副作用とスケジューリングは回帰テストが必要
デフォルト描画Virtual DOM引き続き Virtual DOM依存関係を更新するだけで Vapor へ移行することはない
Vapor Mode3.5 の正式機能としては未提供機能セットが RC、完全な明示的 opt-in性能が重要な一領域から実験できる
アプリサイズVDOM runtime を既定で含む純粋な Vapor アプリは VDOM runtime を省略可能純 Vapor または境界が明確な領域でサイズ効果を得やすい
API 対応範囲Vue 3 API の完全なエコシステムVapor は Vue API のサブセットをサポートOptions API やインスタンスプロキシ関連機能は直接移行できない
VDOM / Vapor 混在対象外vaporInteropPlugin で相互運用標準的な props、イベント、slots は対応済みですが、複雑なネストはテストが必要
イベント委譲ネイティブなリスナー動作rc.2 以降は直接 binding が既定、.delegate で明示的に委譲rc.1 の自動委譲という認識を引き継がない
本番利用安定版現在もプレリリース安定版と上位エコシステムの明示的対応を待つべき

一言でまとめると、

Vue 3.5 の中心は開発体験と SSR 機能の向上、Vue 3.6 の中心はリアクティビティコアと描画アーキテクチャの更新です。

3.5 から 3.6 へ:変化の重心が移った

Vue 3.5 には破壊的変更がなく、多くの改善を業務コードから直接感じられました。

  • Reactive Props Destructure が安定版になった。
  • useTemplateRef() が template ref の整理方法を改善した。
  • onWatcherCleanup() で watcher の cleanup を自然に書けるようになった。
  • useId() が SSR に適した安定 ID を提供した。
  • 非同期コンポーネントが Lazy Hydration に対応した。
  • data-allow-mismatch で許容する hydration 差異を宣言できるようになった。
  • Deferred Teleport とカスタム要素が強化された。

3.6 にも多くの修正がありますが、最も注目すべき alien-signals と Vapor は、どちらもフレームワークの下層にあります。業務コードに新 API を一つも追加しなくても、性能特性、コンパイル結果、ランタイム境界は変わります。

そのためアップグレード方法も変わります。「コンパイルできるか」だけでなく、リアクティブな動作、SSR hydration、コンポーネント間の相互運用、実際の性能を確認してください。

変更点 1:リアクティビティコアが alien-signals へ

Vue 3.6 は @vue/reactivity を大規模に再構築し、その基盤には StackBlitz がオープンソース化した alien-signals が使われています。

大多数のアプリケーション開発者にとって、次のコードはこれまでどおりの Vue です。

import { computed, ref, watchEffect } from 'vue'

const price = ref(99)
const count = ref(2)
const total = computed(() => price.value * count.value)

watchEffect(() => {
  console.log(total.value)
})

変化したのは内部です。依存関係の構築方法、状態のマーク方法、computed がいつ無効になるか、effect が依存グラフをどう伝播するか、そして関係をどう cleanup し再利用するかが変わりました。

アクティブな経路と休眠中の経路から構成される細粒度リアクティブ依存ネットワーク

この図は依存伝播の概念を示したもので、Vue の内部データ構造をフィールド単位で表したものではありません。

性能数値をどう理解するか

Vue core の alien-signals マージ PR では、二種類のマイクロベンチマーク結果が示されています。

  • 多数の refcomputed、effect インスタンスを生成する場面で、サンプルのメモリ使用量が約 2.3 MB から約 2.0 MB へ減り、およそ 13% 削減された。
  • 一つの source が変化した後、多数の computed を読み取る特定のストレスケースで、30 倍を超える性能向上が見られた。

二つ目の数字は目を引きますが、「Vue 3.6 のアプリが 30 倍速くなる」という意味ではありません。示しているのは、以前は規模とともにコストが急増した一部の依存グラフで、新しい伝播アルゴリズムの計算量特性が改善したということです。

実際のページには DOM、layout、network、コンポーネントライブラリ、serialization、業務計算も含まれます。アップグレード前後は、自分のプロジェクトの flame chart、操作遅延、メモリ曲線、bundle 結果で判断し、フレームワークのマイクロベンチマークをそのままアプリの約束にしないでください。

効果を感じやすいプロジェクト

  • 多数の computed が相互依存するデータダッシュボード。
  • 高頻度の変更、フィルター、多くの派生状態を持つエディター。
  • 長時間動作し、多数の effect を生成・破棄するワークベンチ。
  • フィールド数が多く、検証規則と連動関係が複雑なフォーム。
  • Vue のリアクティブ primitive を基盤にした状態管理やツールライブラリ。

通常のコンテンツページも内部改善を受けますが、ユーザーが大きな違いを感じるとは限りません。

特に注意すべきコード

公開 API の refreactivecomputedwatcheffectScope だけを使っていれば、移行リスクは比較的限定的です。本当に注意すべきなのは次のコードです。

  • Vue の非公開リアクティブフィールドを直接読む、または変更する。
  • 非公開の effect、Dep、scheduler の実装詳細へ依存する。
  • リアクティブ関数を monkey patch する。
  • watcher の実行順、同期 flush、cleanup timing に暗黙の仮定がある。
  • 複数の Vue マイナーバージョンに対応するライブラリで、境界テストがない。

内部再構築の意義は、公開 API を保ったまま Vue が実装を交換できることです。逆に、内部実装に依存するコードほど、この種のアップグレードで問題が表面化します。

変更点 2:Vapor Mode は実験的な概念だけではなくなった

Vapor Mode は Vue SFC の新しいコンパイルモードです。従来の Vue template は VNode を生成し、Virtual DOM runtime が新旧ツリーを比較して差分を実 DOM へ反映します。Vapor ではコンパイラが動的部分を事前に認識し、より直接的で細粒度な更新ロジックを生成します。

目標は二つです。

  1. アプリケーションの基礎 bundle サイズを削減する。
  2. 実行時に VNode を生成、走査、比較するコストを減らす。

公式リリースノートによると、Vapor は第三者の js-framework-benchmark で Solid や Svelte 5 に近い水準に達しています。これも「ベンチマークの場面での結果」と理解すべきで、異なるフレームワークと実アプリの性能を一つの順位に圧縮するものではありません。

アップグレードしても Vapor は自動で有効にならない

Vue 3.6 も既定では VDOM を使います。SFC で Vapor を使うには明示的に指定します。

<script setup vapor lang="ts">
import { ref } from 'vue'

const count = ref(0)
</script>

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

同等の入口がほかに二つあります。

<script vapor>
// <script setup vapor> の短縮形
</script>
<template vapor>
  <!-- SFC 全体を Vapor でコンパイル -->
</template>

つまり 3.6 へアップグレードした後も既存の VDOM アプリを維持し、特定のコンポーネントやページだけを選んで移行できます。

純粋な Vapor アプリケーション

アプリケーションが完全に Vapor コンポーネントで構成される場合は、次を使えます。

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

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

このモードは Virtual DOM runtime を取り込む必要がなく、基礎 bundle サイズの効果を最も得やすい方法です。小さな新規アプリ、インタラクティブなツール、技術スタックを明確に制約できる独立ページに向いています。

既存の VDOM アプリケーションで Vapor を使う

既存の createApp() プロジェクトには相互運用プラグインが必要です。

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

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

逆に、Vapor アプリもこのプラグインを導入して VDOM コンポーネントを含められます。ただし VDOM runtime が再び入り、bundle サイズの利点は小さくなります。

Render Function や JSX で書いたコンポーネントも VDOM コンポーネントのままです。純 Vapor アプリで使う場合は相互運用が必要です。

既存の VDOM 領域が明示的な相互運用境界を通じて独立した Vapor 領域へ接続される

私の提案も公式ガイダンスと同じです。二つの描画モードを境界の明確な領域へ整理し、コンポーネント階層の各段で交互にネストしないでください。

例えば、高頻度に更新するデータキャンバスだけを Vapor ページまたは subtree にし、周囲の管理ナビゲーション、dialog、成熟したコンポーネントライブラリは VDOM のままにします。そのほうが効果、障害範囲、ロールバック経路を測定しやすくなります。

rc.2 で最も陥りやすい変更:イベント委譲が明示的 opt-in になった

rc.1 の段階で Vapor を試した場合、この節は特に重要です。

rc.1 では条件を満たすイベントが自動的に document へ委譲されました。しかし、これはネイティブ DOM と標準 Vue の動作と異なります。祖先要素が先に stopPropagation() を呼ぶとイベントは document へ到達せず、子要素の委譲 handler も実行されません。

3.6.0-rc.2 以降、Vapor は既定で DOM listener を要素へ直接 binding します。document レベルの委譲を明示的に使いたい場合だけ、Vapor 専用の .delegate modifier を付けます。

<button @click.delegate="onClick">
  保存
</button>

古い compilerOptions.eventDelegation は削除されました。

移行では二つの作業が必要です。

  1. 既存の compilerOptions.eventDelegation を削除する。
  2. 数が多く、イベントが安定し、伝播経路を検証済みの listener だけに .delegate を使う。

これは全体へ機械的に置換するための最適化ではありません。委譲に価値があるかは、ノード数、ライフサイクル、伝播セマンティクスを合わせて判断します。

Vapor と標準 Vue の互換性境界

Vapor は初日から Vue の歴史的な機能をすべて覆うことを目標にしていません。公式には既存 Vue API のサブセットをサポートし、VNode やコンポーネントの公開インスタンスプロキシへ依存する機能は現在直接利用できません。

機能VDOM コンポーネントVapor コンポーネント
Composition API対応主なプログラミングモデル
Options API対応非対応
app.config.globalProperties対応非対応
getCurrentInstance()現在のインスタンスを返すnull を返す
Render Function / JSXネイティブ VDOMVDOM のまま、混在には interop が必要
v-memo対応対象外 / 非対応
@vue:xxx 要素ライフサイクルイベント対応非対応
コンポーネント template ref公開インスタンス機能を公開$el$props$attrs$slots$refs などを公開しない
カスタム directive標準 directive lifecycle objectVapor 専用の関数インターフェース

slots.default() を副作用のない確認に使わない

VDOM では、先に slots.default() を呼び、返った内容を確認してから fallback を描画するコンポーネントがあります。Vapor で slot を呼ぶと、Block と DOM の生成、リアクティブ effect の登録、hydration 時の既存 SSR DOM の取得が直ちに行われる可能性があります。

次のように書かないでください。

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

const slots = useSlots()
const content = slots.default?.()
const showFallback = !content
</script>

実際の slot 描画は template に任せるほうが安全です。

<template>
  <slot />
</template>

カスタム directive は個別に移行する

Vapor のカスタム directive はノードとリアクティブ getter を受け取り、cleanup 関数を返せます。VDOM directive の mountedupdatedunmounted オブジェクトをそのまま移すものではありません。

多くのカスタム directive に依存するプロジェクトやコンポーネントライブラリでは、独立した移行項目として一覧化し、リアクティブ更新、cleanup、SSR 動作を一つずつ検証してください。

Nuxt、Router、Pinia、コンポーネントライブラリをどう見るべきか

Vue core で利用できることは、その上のフレームワークが Vapor 統合を自動的に完了したことを意味しません。

公式 Vapor Roadmap は Router、Pinia、Nuxt、DevTools、Vue Test Utils などのエコシステム作業を個別に追跡しています。Nuxt はさらに SSR hydration 機能へ依存します。実プロジェクトでは、コンパイラの Vapor 認識、サーバー出力、クライアント hydration、開発ツールでのコンポーネント確認までが一つの完全なチェーンです。

そのため、プロジェクトを二種類に分けて考えます。

通常の Vue / Vite アプリケーション

ブランチ上で 3.6 RC へアップグレードし、既存 VDOM モードを先に検証してから、一つの leaf ページで Vapor を試します。依存関係が比較的直接的なので、問題の原因も特定しやすくなります。

Nuxt、SSR、またはコンポーネントライブラリを多用するアプリ

package override で下層 Vue だけを RC に変え、Vapor 移行が完了したと考えないでください。フレームワーク、build plugin、SSR チェーンが対象バージョンを明示的にサポートすることを確認してから、hydration、ルート遷移、非同期コンポーネント、コンポーネントライブラリとの相互運用をテストします。

Vapor を使わなくても、Vue 3.6 の新しいリアクティビティコアを試す価値はあります。ただし独立ブランチかテスト環境に置くのが安全です。

より安全なアップグレード手順

第 1 段階:Vapor を有効にせず、依存関係だけを更新

通常の Vue / Vite プロジェクトでは、実験ブランチに RC をインストールできます。

pnpm add vue@3.6.0-rc.2

@vue/server-renderer に直接依存している場合は Vue と同じバージョンに揃えます。

pnpm add vue@3.6.0-rc.2 @vue/server-renderer@3.6.0-rc.2

まず従来の VDOM アプリを検証します。

  • unit test と component test。
  • 初期 SSR とクライアント hydration。
  • 複雑な watchcomputedeffectScope
  • 高速なルート遷移後の副作用 cleanup。
  • カスタム directive、Teleport、Suspense、非同期コンポーネント。
  • 開発 build と本番 build。
  • ブラウザコンソールの warning と error。
  • 重要な操作の時間とメモリ基準。

この段階で失敗した場合、原因は Vapor よりも新しいリアクティビティ実装や RC の回帰である可能性が高く、切り分けが簡単になります。

第 2 段階:境界が明確な領域を一つ選ぶ

良い試験領域には通常、次の条件がそろっています。

  • Composition API を使っている。
  • コンポーネントインスタンスへの依存が少ない。
  • 複雑な VDOM コンポーネントライブラリへ依存しない。
  • 更新頻度が高く、実際の性能負荷がある。
  • 独立したルートまたは明確なコンポーネントツリー境界がある。
  • 再現可能な性能テストがある。

移行前の JavaScript サイズ、操作遅延、CPU 時間、メモリを記録してから Vapor を有効にします。基準がなければ「技術的に動いた」を「移行する価値があった」と誤認しやすくなります。

第 3 段階:相互運用と SSR を検証

最低でも次の組み合わせを確認します。

  1. VDOM 親コンポーネントに Vapor 子コンポーネント。
  2. Vapor 親コンポーネントに VDOM 子コンポーネント。
  3. props、emit、双方向 binding。
  4. default、named、scoped slot。
  5. Suspense、非同期コンポーネント、error boundary。
  6. サーバー出力、hydration、mismatch recovery。
  7. unmount 後の watcher、event、directive cleanup。

rc.2 の修正には hydration、Suspense、slot anchor、VDOM interop に集中する項目が多くあります。これらの領域が急速に収束している証拠であると同時に、今最も重点的にテストすべき場所でもあります。

第 4 段階:安定版を待って本番スケジュールを決める

RC は機能セットがほぼ確定し、回帰と境界問題の発見へ重点が移った状態です。エコシステム全体が安定したという意味ではありません。

本番プロジェクトは少なくとも次の条件を満たす必要があります。

  • Vue 3.6 の安定版が公開されている。
  • 利用するフレームワークと build tool が明示的に対応している。
  • 主要コンポーネントライブラリが相互運用テストを通過している。
  • DevTools、テストツール、SSR チェーンが利用できる。
  • 性能効果が移行・保守コストを上回る。
  • いつでも VDOM へ戻せる。

推奨しない四つのこと

1. RC を通常の patch と同じように扱わない

プレリリースでは動作が変わる可能性があります。rc.1 から rc.2 へのイベント委譲の変更が最も分かりやすい例です。

2. 「Vapor を使う」ために全コンポーネントを移行しない

ナビゲーション、静的コンテンツ、更新頻度の低い設定ページでは意味のある効果を得られないかもしれません。移行率ではなく性能 bottleneck を優先します。

3. マイクロベンチマークをアプリの約束にしない

「30 倍超」は特定のリアクティブストレスケース、「Solid や Svelte 5 と同水準」は第三者 benchmark の結果です。技術的な方向性は証明しますが、プロジェクト自身の測定には代えられません。

4. エコシステム境界を無視しない

Vue core、SFC compiler、Vite plugin、Nuxt、SSR、Router、Pinia、コンポーネントライブラリ、DevTools、テストツールが一緒に開発体験を構成します。一つの package を RC にするだけでは、チェーン全体の更新にはなりません。

プロジェクト種別ごとの提案

プロジェクト種別今試す価値提案
小規模な新規ツール、社内実験ある純 Vapor を試し、bundle サイズと操作性能を測る
既存 Vue SPAブランチ上で試す価値があるまず VDOM を維持し、性能が重要な一ページだけを移行
Nuxt / SSR サイト研究には適するが本番は待つフレームワーク対応を確認し hydration を重点的にテスト
コンポーネントライブラリ早期に互換テストを始めるinstance proxy、slots、カスタム directive、interop を確認
大規模ダッシュボード / エディターstress test の価値が高いalien-signals と Vapor それぞれの効果を分けて比較
コンテンツ中心のサイト優先度は低い限定的な効果のために複雑さを増やさず、安定版と成熟したエコシステムを待つ

最終的な判断

Vue 3.6 RC の最も価値ある点は、業務コードですぐ使える新 API の数ではなく、二つの長期的な問題を同時に進めていることです。

  • Vue のリアクティビティは、より複雑な依存グラフでも効率を保てるか。
  • Vue の template は、慣れた開発体験を保ちながら Virtual DOM のコストを必須ではなくせるか。

alien-signals は一つ目に答え、Vapor は二つ目に答えようとしています。

既存プロジェクトで最も合理的な戦略は、まず 3.6 をリアクティビティコアの更新としてテストし、その後 Vapor を任意の局所コンパイルモードとして評価することです。二つを分けて検証すれば、性能変化の原因を理解でき、リスクを明確な境界内に保てます。

Vue 3.6 はまだ「全員が今日アップグレードすべき」段階ではありません。しかし「すべての Vue チームが理解を始める価値がある」段階には達しています。


資料と注記

この記事のアップグレード提案は、公式資料とエンジニアリング経験に基づく私の判断です。AI が資料整理と言語校正を補助しましたが、各プロジェクトでは自身のテスト結果を基準にしてください。

記事はここまで
READER CHANNEL

コメント

00
まだコメントはありません。最初の返信を残してみませんか。