Vue

Vapor Mode: рендеринг без virtual DOM

Классический Vue при изменении состояния строит новое виртуальное дерево, сравнивает его со старым и применяет разницу к настоящему DOM. Это надёжно, но сам diff стоит процессорного времени и памяти на каждый рендер. Vue 3.6 предлагает Vapor Mode: компилятор анализирует шаблон на этапе сборки и генерирует код, который при изменении реактивного значения трогает ровно тот узел DOM, что зависит от него. Никакого virtual DOM в рантайме, производительность ближе к SolidJS, включается по одному компоненту.

  • Таблица на десятки тысяч строк: точечное обновление ячейки вместо diff всего дерева на каждое изменение
  • Дашборд реального времени: метрики обновляются каждую секунду, Vapor убирает накладные расходы diff
  • Встраиваемый виджет: меньший рантайм и быстрый старт там, где важен вес и отзывчивость
  • Редактор с тысячами реактивных полей: прямые операции с DOM вместо пересборки виртуального дерева
  • Гибридное приложение: тяжёлый список в Vapor-компоненте, остальной UI на классических компонентах

Предварительные знания

  • Глубокая реактивность Vue: как ref и зависимости отслеживают изменения
  • Идея virtual DOM и reconciliation из ранних уроков
  • Понимание разницы между этапом компиляции и рантаймом

Стоимость virtual DOM

В классическом Vue компонент при каждом рендере возвращает описание UI, виртуальное дерево лёгких объектов. Vue сравнивает его с предыдущим деревом (reconciliation) и применяет к настоящему DOM только разницу. Подход устойчив и предсказуем, но сам diff и создание виртуальных узлов стоят CPU и памяти, и эта цена платится при каждом обновлении, даже если изменилось одно значение.

На небольшом UI цена diff незаметна, и virtual DOM остаётся отличным выбором. Она становится ощутимой на больших, часто обновляемых деревьях: таблицы на десятки тысяч строк, дашборды реального времени, редакторы с множеством реактивных полей.

Ключевая идея: diff делает работу пропорционально размеру дерева, а не размеру изменения. Изменили одну ячейку, а сравнить пришлось значительную часть структуры. Именно эту пропорциональность Vapor Mode стремится убрать.

В чём состоит цена virtual DOM в классическом Vue при обновлении?

Как Vapor компилирует шаблон

Vapor Mode переносит работу с рантайма на этап компиляции. Компилятор анализирует шаблон SFC и видит, какие узлы DOM зависят от каких реактивных значений. Он генерирует код, который создаёт настоящие DOM-узлы один раз, а при изменении значения обновляет точечно только связанный узел. Виртуального дерева и diff в рантайме нет вовсе.

  • Классический рендер — Рантайм строит виртуальное дерево, делает diff, применяет разницу. Работа пропорциональна размеру дерева на каждое изменение
  • Vapor рендер — Компилятор заранее связал узлы с реактивными значениями. При изменении трогается ровно зависимый узел. Работа пропорциональна размеру изменения

Этот подход называют fine-grained реактивностью: обновление адресует конкретный узел, а не перерисовывает компонент. Та же модель лежит в основе SolidJS, и Vapor Mode приносит её в Vue, сохраняя привычный синтаксис SFC.

Что Vapor Mode делает на этапе компиляции, чего нет в классическом подходе?

Производительность и гибридное использование

Без virtual DOM Vapor-компонент несёт меньше рантайма и обновляется дешевле. Выигрыш растёт с объёмом данных и частотой обновлений: на таблице в десятки тысяч строк или дашборде, который тикает каждую секунду, экономия diff заметна. На небольшом статичном UI разница невелика, и классический режим там вполне хорош.

СценарийКлассическийVapor
Маленький статичный UIОтличноРазница незаметна
Таблица на 50k строкDiff дорогойТочечное обновление
Дашборд реального времениНакладные расходыМеньший рантайм
Встраиваемый виджетПолный рантаймЛёгкий рантайм

Vapor включается по одному компоненту, а не для всего приложения сразу. Vapor-компоненты и классические сосуществуют в одном дереве, поэтому миграция инкрементальная: тяжёлый список переводят в Vapor, остальной UI остаётся как есть. Это снижает риск и не требует переписывать приложение целиком.

Vapor это не замена классическому Vue, а второй режим под другой профиль нагрузки. Решение принимают по данным профайлера: если diff не узкое место, переход на Vapor не даст заметного выигрыша и лишь добавит экспериментальный код.

Как Vapor Mode сочетается с классическими компонентами в одном приложении?

Экспериментальный статус в 2026

В 2026 году Vapor Mode остаётся экспериментальным. Не все возможности Vue поддерживаются в Vapor-компонентах одинаково, часть библиотек экосистемы рассчитана на virtual DOM и может работать иначе или не работать, а API и поведение могут измениться между версиями. Это накладывает ограничения на использование в проде.

Экспериментальный статус означает, что Vapor не ставят на критичный путь без запасного плана. Его обкладывают тестами, ограничивают изолированными тяжёлыми компонентами и следят за заметками к релизам Vue, чтобы вовремя поймать изменения API.

Разумная тактика: применять Vapor точечно там, где профайлер показал, что diff это узкое место, и где совместимость с используемыми библиотеками проверена. Для остального UI классический режим в 2026 году остаётся стабильным дефолтом.

Перед внедрением Vapor проверяют две вещи: подтверждает ли профайлер выигрыш на конкретном компоненте и совместимы ли нужные библиотеки. Без обеих галочек переход добавляет риск без гарантированной пользы.

Что означает экспериментальный статус Vapor Mode для использования в 2026 году?

Связь с другими темами

Урок про рычаг производительности на уровне рендеринга. Рядом стоят разбиение бандла и SSR:

  • Асинхронные компоненты и code-splitting — Другой рычаг: снижение веса бандла, тогда как Vapor снижает стоимость рендеринга
  • SSR и Nuxt 4 — Режим рендеринга влияет на серверный рендер и гидратацию

Итог

  • Классический Vue использует virtual DOM: новое дерево, diff со старым, применение разницы к настоящему DOM на каждый рендер
  • Vapor Mode компилирует SFC в код, который при изменении реактивного значения трогает ровно зависимый узел DOM, без virtual DOM
  • Это даёт производительность уровня fine-grained реактивности SolidJS и меньший рантайм, особенно на больших объёмах данных
  • Vapor включается по компоненту через <script setup vapor>, а классические и Vapor-компоненты сочетаются в одном приложении
  • В 2026 году Vapor Mode всё ещё экспериментальный: не все возможности и библиотеки поддерживаются, API может меняться

Связанные уроки

  • vue-33-async-components — Code-splitting режет вес бандла, Vapor режет стоимость рендеринга. Оба про производительность, но на разных уровнях
  • vue-36-ssr-nuxt — Vapor влияет и на серверный рендеринг с гидратацией, что напрямую касается SSR и Nuxt
Vapor Mode: рендеринг без virtual DOM

0

1

Войти