【日本語版】All we know about Vue 3's Vapor Mode

# 初めに

![e2e526c6-1a25-419e-9222-f6dfecfca6d1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/821707/cb6842aa-7d01-2c09-b5cf-f6d2642ad2cd.png)


本記事は [All we know about Vue 3's Vapor Mode](https://icarusgk.hashnode.dev/vue-3-vapor-mode) の日本語翻訳版です。

このブログは現時点で出回っている Vapor Mode についてのリソースでおそらく最も体系的にまとめられているもので、主に Evan You 氏の講演やインタビューをもとに書かれています。

このブログを書いてくださったのは [:icarus.gk](https://twitter.com/icarusgkx) 氏で、彼はいつも Vue のアップデートのまとめや、機能の紹介に関して素晴らしい発信をしています。

日本語翻訳を公開する件について [:icarus.gk](https://twitter.com/icarusgkx) 氏 は快く了承してくださいました。
この場を借りて感謝したいと思います。

また、コンテンツの最後に幾つかの注釈を加えました。
こちらは元のブログにはないものであり、筆者 (@ubugeeei) が追記しているという点に注意してください。

# Vapor Mode とは？ 🧐

Vapor Mode は、[Solid.js](https://www.solidjs.com/) から着想を得た新しい代替コンパイル戦略です。これにより、コードがより効率的な JavaScript 出力にコンパイルされることで、アプリのパフォーマンスが向上します。

アプリレベルで使用する場合、仮想 DOM を完全に削除することができ、アプリのバンドルサイズを削減することができます。

**✅ 利点**

- より高速なパフォーマンス
- より少ないメモリ使用量
- より少ないランタイムのコード

Solid.js は Vue と非常に似たリアクティビティシステムを持っており、両者とも、Proxy [^1] を使用した読み取りベースの自動トラッキングによるリアクティビティシステムを実装しています。これが Vue が [Solid.js](https://www.solidjs.com/) と同様のコンパイル戦略を実装できる理由です。

# Vapor Mode はどのように機能するのか？ 🤔

いつもと同じ `.vue` のシングルファイルコンポーネントを使用して、Vapor Mode はより高速な JavaScript 出力にコンパイルすることができます。

![compilation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/821707/57101b04-e37e-4fa5-b587-102c686404e9.png)

最高のパフォーマンスを最適化するために、Vapor Mode は Vue の機能のサブセットのみをサポートします。これには、新しい Composition API と `<script setup>` を使用した `.vue` SFC が含まれます。詳細は [Vue's Year in Review](https://blog.vuejs.org/posts/2022-year-in-review) で読むことができます。

# 現在のアプローチはどうなのか？

現在、Vue はハイブリッド仮想 DOM / コンパイラのアプローチを取っています。コンパイラは SFC のテンプレートを取り、分析して仮想 DOM にフィードします。

この [コンパイラー情報に基づく仮想 DOM](https://ja.vuejs.org/guide/extras/rendering-mechanism#compiler-informed-virtual-dom) のアプローチにより、Vue は Svelte 4 のような 仮想 DOM レスのツールよりも DOM 操作を行う際にわずかに優れたパフォーマンスを発揮することができます。

https://x.com/icarusgkx/status/1693620200543862852

# Vapor Mode はどのように使用できる？ [^2]

## コンポーネントレベルで

`.vapor` のファイル名の接尾辞を使用して有効にすることができます。

![posfix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/821707/5327879f-6149-18a8-de09-215b91fedb7e.png)
最終的な目標は、Vapor コンポーネントと非 Vapor コンポーネントを同じアプリ内で自由に混在させることです。

![tree.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/821707/f28cd142-c548-302f-31be-63cee736c070.png)
**📝 \* 注意**
最初は、Vapor Mode は 仮想 DOM に統合された Vapor 専用のツリーで始まり、そこから相互運用性を改善していく予定です。

## アプリレベルで

![app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/821707/9e819d6e-bbf3-99cc-302a-a9fafc4bda80.png)

この方法でコンパイルされたアプリは、仮想 DOM ランタイムを完全に削除し、`@vue/reactivity` と Vapor Mode のランタイムヘルパーのみを含みます。この方法で書かれたアプリのベースラインサイズは約 6kb で、現在の 仮想 DOM を使用した Vue 3 アプリのベースラインサイズの約 50kb と比較して、88%の削減です！ 🤯

## Key Points

- **既存のコードベースに影響を与えないオプションの機能です。**
  Vue のバージョンを Vapor Mode を含むバージョンにアップグレードする場合、これは Vapor Mode に関連する破壊的な変更を導入しません。
- **Vapor Mode は仮想 DOM コンポーネントと相互運用できます。**
  したがって、Vuetify のような仮想 DOM を使用するライブラリを使用したい場合、Vapor Mode は引き続きサポートできます。

# Vapor Mode のステージ [^3]

開発中ですが、いくつかのニュースがあります：

## Stage 1: コア機能のランタイム

Vapor ランタイムヘルパーがすべて導入され、これらのヘルパーは基本的に生成コードをサポートするコードです。このステージはほぼ完了しています。

**❇️ ゴール**

- コアディレクティブ（`v-on、v-if、v-for`など）とコンポーネントツリーのサポート
- パフォーマンスの前提条件の検証
- 既存の SSR 出力とのハイドレーション互換性

## Stage 2: コア機能のコンパイラ

**❇️ ゴール**

- 共有コード生成 IR（中間表現）
- JSX AST / テンプレート AST - IR - Vapor Mode コード

### なぜ中間表現が必要なのですか？

Vapor Mode のコンパイルプロセスでは、仮想 DOM の欠如により手動のレンダリング関数の作成の必要がなくなります。ただし、一部のユーザーは JavaScript の広範な柔軟性が必要です。そのような場合、JSX を Vapor コードにコンパイルすることが可能です。

テンプレートと JSX の両方は、同じ中間表現に変換され、最終的に Vapor コードにコンパイルされます。

![ir.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/821707/6b7ce0c7-f919-6e79-6d77-f8363e13e0bd.png)

## Stage 3: 統合

Vue は Vapor を既存のアプリケーションにシームレスに組み込むことを目指しており、現在のセットアップに対して変更を必要としません。コンポーネントレベルでオプトインする柔軟性があり、アプリケーションの一部のサブセットまたはパフォーマンス重視のエリアに徐々に導入することができます。

**❇️ ゴール**

- スタンドアロンの Vapor アプリのためのツールサポート
- 既存のアプリ内での Vapor コンポーネントの実行
- Vapor 内での vDOM コンポーネントの実行

## Stage 4: 機能の同等性

最初のリリースでは、Vapor Mode は基本的なコア機能のみを提供し、`<Transition />`、`<KeepAlive />`、`<Teleport />`、`Suspense` などのより補助的な機能は、Vue チームが以前のゴールをすべて整理した後に実装されます。

# まとめ

- **Vapor Mode は、Vue.js によって開発されている新しいパフォーマンス指向のコンパイル戦略**です。
- **同じテンプレートを使用します**（Composition API と`<script setup>`を使用している場合）し、より高パフォーマンスな出力を生成します。
- **段階的に採用可能** - Vapor Mode を個々のコンポーネントまたはアプリ全体に有効にすることができます。
- **最終的な目標は、Vapor コンポーネントと非 Vapor コンポーネントを問題なく混在させることです**ただし、Vapor Mode は最初に vDOM に統合された Vapor 専用のツリーで始まり、そこから相互運用性を改善していく予定です。

# このブログのために使用されたコンテンツ

[The Vue Point - 2022 Year in Review](https://blog.vuejs.org/posts/2022-year-in-review)  
Jan 1, 2023

[Vue: What to Expect in 2023 by Evan You](https://www.youtube.com/watch?v=OrT0tHGXyqE&t=1250s) - Vue.js Nation 2023  
Feb 1, 2023

[State of Vuenion 2023](https://www.youtube.com/watch?v=I5mGNB-4f0o&t=1219s) - Vuejs Amsterdam 2023  
Mar 1, 2023

[Vue Mastermind Evan You answers Vue devs' questions](https://www.youtube.com/watch?v=BqHzQcFwk0I&t=899s) - Vue Mastery  
Jun 22, 2023

[State of Vuenion 2023](https://www.youtube.com/watch?v=y-hN5Q_lb9A&t=1328s) VueConf US 2023  
Jul 11, 2023

---

以下、[@ubugeeei](https://qiita.com/ubugeeei) による注釈

[^1]:
    Solid.js について、 createSignal に関しては Proxy オブジェクトではなく、getter 関数を扱うインタフェースになっています。
    [参考: [solid/packages/solid/src/reactive/signal.ts/readSignal](https://github.com/solidjs/solid/blob/51c94859098170c913c02a0fe1d9003d1664d130/packages/solid/src/reactive/signal.ts#L1254)]

    getter 関数のインタフェースになっていない props に関しては、Proxy を使用しているようでした。
    [参考: [solid/packages/solid/src/render/component.ts](https://github.com/solidjs/solid/blob/51c94859098170c913c02a0fe1d9003d1664d130/packages/solid/src/render/component.ts)]
    (※複数箇所あるので特定の行へのリンクになっていません。Proxy が使われているところがちらほらあると思います。)

    また、Vue.js に関しても、基本となる `reactive` 関数に関しては Proxy で実装されていますが、それをラップした `ref` の実装に関しては、`value` への get/set は Proxy ではなく class の getter/setter で実装されています。
    [参考: [vue/packages/reactivity/src/ref.ts](https://github.com/vuejs/core/blob/04d2c05054c26b02fbc1d84839b0ed5cd36455b6/packages/reactivity/src/ref.ts#L151-L166)]
    value よりもネストしたところでは proxy の get/set が動きます。

[^2]:
    Vapor Mode は現在研究開発段階です。今後の開発の中で大きく変更がある可能性があります。
    これらのインタフェースは現時点での草案であることに注意してください。

[^3]:
    [vuejs/core-vapor](https://github.com/vuejs/core-vapor) というリポジトリをご存知の方もいるかもしれませんが、こちらのリポジトリが公開されたのは icarus 氏のブログが投稿されてから数ヶ月後です。
    このリポジトリが公開される前までにも、Evan 氏を含む Vue.js のコアチームのメンバーがプライベートな場で議論を重ね、開発は進められていたようなので、このブログ(インタビューの発言など)の進捗と、このリポジトリの進捗状況にはズレがあります。
    このリポジトリについての説明や Vapor Mode の近況については別記事でまとめる予定があるのでお楽しみに！