Svelte против React и Vue: компилятор вместо виртуального DOM
React даёт вам движок и просит подстраиваться под его правила. Svelte компилирует ваш код и убирает движок с дороги.
«Виртуальный DOM — это чистые накладные расходы» — провокационный тезис команды Svelte, который заставил всю индустрию пересмотреть устройство фронтенд-фреймворков.
Чтобы понять, зачем вообще нужен Svelte, полезно увидеть, какую проблему он решает у конкурентов. Все современные фреймворки решают одну задачу: держать интерфейс в синхронизации с данными. Когда меняется число в переменной, на экране должно поменяться число. Вопрос только в том, как это синхронизировать. И вот тут подходы расходятся радикально.
React выбрал виртуальный DOM. При каждом изменении состояния React заново вызывает функцию компонента, строит лёгкую копию дерева элементов в памяти, сравнивает её с предыдущей копией и вычисляет минимальный набор изменений для настоящего DOM. Это работает и работает надёжно, но у этого есть цена: на каждое обновление выполняется построение и сравнение деревьев. Чтобы эта цена не убивала производительность, React-разработчики учат хуки, мемоизацию, useMemo, useCallback и правила зависимостей — целую дисциплину борьбы с лишними перерисовками.
Vue занимает промежуточную позицию: он тоже использует виртуальный DOM, но добавляет систему реактивности на прокси, которая точнее отслеживает зависимости. Angular — это полноценная платформа с собственным механизмом обнаружения изменений. Все они — рантайм-фреймворки: их движок едет к пользователю вместе с вашим кодом.
Svelte отказывается от виртуального DOM целиком. Раз уж компилятор и так анализирует ваш шаблон, он может прямо во время сборки выяснить, какие узлы DOM зависят от каких переменных, и сгенерировать прямые обновления. Никакого дерева в памяти, никакого диффинга, никакой реконсиляции. Изменение цены в строке 4372 таблицы превращается в один вызов textNode.data = newPrice именно для этой ячейки.
Сравним семейство компиляторных фреймворков. Solid.js идёт по похожему пути с сигналами, но без шага компиляции шаблона в той же мере. Svelte уникален тем, что компилирует и реактивность, и разметку. Это не значит, что Svelte всегда «лучше» — у React огромная экосистема и рынок труда. Но как инструмент для построения быстрых интерфейсов с минимумом церемоний Svelte стоит особняком.
Как это работает под капотом
Давайте на чистом JavaScript смоделируем, почему диффинг стоит дорого, а адресное обновление — дёшево. Представим, что нам нужно обновить одну ячейку в большом списке. Наивный «виртуальный DOM» пройдётся по всему массиву, чтобы найти отличие. Адресный подход сразу знает индекс.
// Имитация: что делает diff против адресного обновления
const oldData = Array.from({length: 10000}, (_, i) => i);
const newData = oldData.slice();
newData[4372] = 999; // изменилась одна ячейка
// Подход 'виртуального DOM': сравнить всё, чтобы найти отличие
let diffOps = 0;
for (let i = 0; i < newData.length; i++) {
if (newData[i] !== oldData[i]) diffOps++; // нашли — но прошли по всем
}
console.log('diff просмотрел элементов:', oldData.length, 'нашёл изменений:', diffOps);
// 'Скомпилированный' Svelte-подход: знаем индекс заранее
const targetIndex = 4372;
console.log('адресное обновление: 1 операция в индекс', targetIndex);Попробуй сам ▶ — вставь код в консоль браузера (F12 → Console) и нажми Enter, чтобы увидеть вывод.
Конечно, настоящие реализации виртуального DOM умнее этого наивного цикла, но суть верна: работа диффинга растёт вместе с размером дерева, а адресное обновление — нет. Именно поэтому Svelte хорошо держит большие списки.
Частые ошибки
- Переносить React-привычки. В Svelte не нужно мемоизировать обработчики и значения — компилятор уже отслеживает зависимости точечно.
- Думать, что отсутствие vDOM значит отсутствие правил. Реактивностью всё равно нужно управлять осознанно, просто инструменты другие (руны).
- Выбирать фреймворк по бенчмаркам «hello world». Смотрите на сопровождаемость, экосистему и команду, а не только на цифры.
Best practices
- Если вы пришли из React, сознательно «разучивайтесь» от хуков зависимостей — в Svelte они не нужны.
- Используйте ключи в циклах (
{#each items as item (item.id)}), чтобы компилятор делал точечные обновления строк. - Не выбирайте фреймворк религиозно. Svelte силён там, где важны скорость, размер бандла и приятный авторский опыт.
Что выбрать для своего проекта
Архитектурное превосходство не означает, что Svelte всегда правильный выбор. У React огромная экосистема готовых библиотек, гигантское сообщество и обширный рынок труда — для многих команд это решающие факторы. Svelte же выигрывает там, где важны скорость загрузки, размер бандла и скорость разработки небольшой командой. Хорошее правило: если вы строите контентный сайт, дашборд, виджет или приложение, где производительность на слабых устройствах критична, Svelte раскроется во всей красе. Если же вам нужна редкая нишевая библиотека, которая существует только под React, или вы нанимаете большую команду, где все знают React, — взвесьте удобство экосистемы против технических преимуществ. Главное — не выбирать фреймворк религиозно: смотрите на конкретную задачу, команду и горизонт сопровождения проекта, а не только на цифры синтетических бенчмарков.
Итог: главное архитектурное отличие Svelte — отказ от виртуального DOM в пользу скомпилированных адресных обновлений. Это убирает целый класс задач по оптимизации и делает приложения быстрыми по умолчанию.