Разбираем компиляторный подход к веб-производительности: чем он отличается от рантайм-фреймворков и как выбрать баланс скорости и итераций в продукте.

«Медленный сайт» для пользователя - это не метрики в отчете, а моменты, когда он ощущает задержку. Чаще всего это происходит в трех местах: на старте, при отклике на действие и во время прокрутки.
Старт. Страница вроде бы открылась, но интерфейс еще «не живой»: кнопки не реагируют, фильтры не работают, поля ввода печатают с задержкой. Частая причина - браузер скачал много JavaScript и занят разбором и выполнением кода, прежде чем сможет нормально обрабатывать клики.
Отклик. Пользователь нажимает «Показать еще», меняет фильтр, открывает модалку, а ответ приходит с паузой. В реальных продуктах это обычно не один большой «фриз», а серия мелких задержек, которые накапливаются и раздражают. Отклик проседает, когда приложению приходится слишком много делать в рантайме: пересчитывать состояние, запускать лишние эффекты, провоцировать повторные рендеры там, где можно было обновить небольшой кусок.
Скролл и анимации. «Дерганый» список, скачущие элементы, рывки при прокрутке почти всегда означают, что главный поток занят. Типовые причины: тяжелые компоненты, частые перерисовки, большие списки без виртуализации, обработчики событий, которые выполняются слишком долго.
«Быстро на моем ноутбуке» не равно «быстро у клиентов». У людей может быть слабее CPU, хуже сеть, меньше памяти, старее браузер, включены расширения. Плюс многие используют сайт параллельно с мессенджерами и десятком вкладок, и тогда лишние 200-300 мс работы начинают бросаться в глаза.
Производительность влияет не только на ощущения, но и на бизнес. Когда интерфейс тормозит, пользователи чаще ошибаются, бросают сценарий на полпути и реже возвращаются. А поддержка получает жалобы «ничего не работает», хотя формально ошибок нет - просто все реагирует слишком медленно.
Rich Harris задал простой вопрос: почему мы заставляем браузер делать так много работы каждый раз, когда пользователь взаимодействует с интерфейсом? Его имя часто связывают со Svelte, потому что там эта идея доведена до практики: часть того, что обычно делает фреймворк в браузере, выполняется заранее, на этапе сборки.
Смысл в том, чтобы уменьшить объем «универсальной» логики в рантайме и заранее подготовить код под конкретное приложение. Вместо того чтобы привозить в браузер движок, который должен уметь «все», мы отдаем более прямые инструкции: что именно менять в DOM, когда меняются данные.
Это компиляторный подход. Он отличается от формата «еще одной библиотеки» тем, что библиотека добавляет слой выполнения поверх приложения, а компиляция меняет само приложение на выходе сборки. В итоге обычно уменьшается объем кода, который нужно загрузить и выполнить, и сокращается работа, которую приходится повторять при каждом обновлении состояния.
Представьте форму с валидацией, подсказками, зависимыми полями и кнопками, которые включаются и выключаются по условиям. В рантайм-ориентированном подходе рядом живет большой механизм: отслеживание зависимостей, общий цикл обновлений, универсальные обработчики. В компиляторном подходе значительная часть решений принимается заранее, а в браузере остаются более прямые обновления.
Рантайм-тяжелый фреймворк - это когда заметная часть работы делается уже в браузере во время запуска и работы приложения. Пользователь получает не только ваш код, но и слой абстракций: как описывать интерфейс, как хранить состояние, как считать изменения и как обновлять DOM.
На практике это чаще всего означает больше JavaScript в бандле и больше шагов между «поменялась кнопка» и «браузер отрисовал новое состояние». Чем больше универсальности «из коробки», тем больше кода нужно привезти на клиент.
Обычно вы платите тремя вещами: весом рантайма (механики рендера, реактивности, событий), универсальными слоями с проверками и обертками (чтобы один подход работал для множества сценариев), а также накладными расходами на обновления (нужно вычислить, что изменилось, и применить изменения аккуратно).
Эта цена не всегда видна как один большой тормоз. Чаще это мелкие задержки: чуть дольше первый рендер, чуть тяжелее скролл, чуть заметнее лаг при фильтрах или в сложной форме. Особенно чувствительно это становится, когда интерфейс часто обновляется (таблицы, графики, фильтры) или когда устройство слабое (бюджетные смартфоны, старые ноутбуки).
При этом рантайм-тяжелый выбор бывает вполне оправдан. Большой команде часто важнее общие правила и зрелая экосистема, а продукту с долгим горизонтом - предсказуемость, обновления и понятные инструменты.
Если вы смотрите в сторону компиляции, полезнее задавать не вопрос «кто быстрее в тесте», а вопрос «сколько лишней работы мы переносим в браузер ради удобства разработки и масштабирования команды».
Компиляторный подход строится на идее, что многие решения можно принять заранее, во время сборки, а не на устройстве пользователя.
Вместо того чтобы привозить в рантайм «движок компонентов», компилятор превращает шаблоны и реактивность в обычный JavaScript, который напрямую создает и обновляет DOM. За счет этого в браузере меньше «служебной» логики, а обновления чаще сводятся к точечным операциям: поменялось значение - меняем конкретный текстовый узел, атрибут или класс.
Практически это обычно дает несколько эффектов:
Как это ощущается: в кабинете есть список заявок и панель фильтров. Пользователь быстро кликает несколько чекбоксов и вводит текст. При компиляции обновляются в основном те части интерфейса, которые действительно зависят от фильтра, а не запускается общий «механизм обновления» для всего подряд.
Компиляция не спасает от плохих решений. Если вы рендерите тысячи строк без виртуализации, делаете тяжелые вычисления при каждом вводе или дергаете сеть без дебаунса, это не станет бесплатным.
Есть и организационная сторона. Чтобы выигрыш проявился, нужны аккуратные привычки: не плодить лишние реактивные зависимости, не хранить «весь мир» в одном глобальном состоянии, следить за тем, что пересчитывается при каждом изменении. В некоторых динамических паттернах приходится выбирать компромисс: чуть больше кода руками ради предсказуемых обновлений.
Самообман обычно начинается с одного числа из отчета. Страница получает «90+», и кажется, что все хорошо. Но продукту важнее другое: когда человек впервые видит полезный экран и как быстро интерфейс отвечает на действия.
Меряйте то, что реально ощущается:
Синтетические тесты полезны, но это лаборатория: фиксированное железо и близкие к идеальным условия. Реальность - слабый телефон, экономный режим, фоновые приложения, нестабильная сеть. Поэтому одного Lighthouse мало.
Рабочий подход - держать две группы данных: лабораторные замеры (чтобы сравнивать изменения между сборками) и проверки на реальных устройствах или хотя бы в приближенных условиях (троттлинг сети, ограничение CPU). Так быстрее видно, где выигрыш дает подход и архитектура, а где проблема в данных, изображениях или логике.
Чтобы не спорить «на ощущениях», выберите 2-3 сценария и меряйте их одинаково каждый раз. Например: холодный запуск до момента, когда можно нажать основную кнопку; применение фильтра и отмена; переход в карточку и назад.
Выбор между компиляцией и тяжелым рантаймом обычно сводится к одному вопросу: где вам дороже время - у пользователя или у команды.
Начните с 3-5 главных сценариев: открыть список заказов, применить фильтр, отредактировать карточку, сохранить форму, открыть график. Для каждого отметьте критичность: «каждый день и много раз» или «редко и можно подождать».
Дальше задайте пороги, чтобы обсуждение было конкретным: какой объем JavaScript вы готовы привозить на типовую страницу и какой отклик считаете нормальным (например, реакция на клик и фильтр около 100 мс, первый полезный экран - за 2-3 секунды на среднем устройстве).
Смотрите на три вещи: сложность UI и частоту обновлений (таблицы, графики и живые фильтры сильнее страдают от лишней рантайм-работы), команду и сроки (что уже умеют, кого реально нанять, сколько времени есть на обучение), а также цену оптимизаций (компиляция часто дает выигрыш в рантайме, но может потребовать других привычек при разработке и отладке).
Дальше выбирайте архитектуру: чистая компиляция, рантайм-ориентированный фреймворк, гибрид или разделение по страницам (например, часть как MPA/SSR, часть как SPA). И обязательно заранее договоритесь о контроле: 2-3 метрики перед релизом и повтор после крупных изменений.
В продакшене скорость ощущается не только в браузере, но и в команде: как быстро вы выпускаете правки, проверяете гипотезы и откатываете неудачные изменения. Иногда разница между «очень быстро» и «мгновенно» для пользователя почти незаметна, а разница между релизом за день и релизом за неделю - критична.
Итерации ускоряют практичные вещи: готовые UI-компоненты, шаблоны страниц, нормальная отладка, понятные ошибки, предсказуемая сборка. А вот где время реально теряется - сложная настройка, хрупкие зависимости, плагины, которые ломаются после обновления, и «магия», которую никто не понимает.
Компромисс часто выглядит так: вы соглашаетесь на чуть более тяжелый рантайм, зато получаете стабильный набор инструментов и быстрый выпуск фич. Компиляция может дать ощутимый бонус по отклику и плавности, но не должна превращаться в религию, если продукту важнее темп.
Первая ловушка - пытаться «ускорить все сразу». Пользователи обычно живут на 2-3 экранах. Начинайте с мест, где задержка бьет по делу: ввод в фильтры, прокрутка списка, переключение вкладок.
Вторая ошибка - считать, что «меньше бандл = всегда лучше». Маленький бандл помогает старту, но цена может быть в другом: сложнее привычные паттерны, меньше готовых библиотек, больше времени на найм и обучение.
Третья - смешивать подходы без границ. Если часть интерфейса на одном стеке, часть на другом, а правила не описаны, вы получаете два состояния, два набора компонентов и сюрпризы в сборке и роутинге. Если комбинировать, то по понятным границам: отдельный виджет, отдельный экран, отдельный продукт.
Четвертая - не учитывать поддержку. Фреймворк - это не только скорость рендера, но и обновления, миграции, качество инструментов, обучение новичков, типичные баги. Самая «быстрая» технология становится медленной, если каждую неделю вы воюете с настройками и несовместимостями.
Пятая - оптимизировать до появления проблемы и не проверять на реальных устройствах. Эмулятор на мощном ноутбуке часто врет.
Перед выбором полезно на 20 минут забыть про спор «рантайм vs компиляция» и описать ваш продукт максимально приземленно. Выигрыш от подхода не спасет, если проблема в данных, макетах или отсутствии измерений.
Ответьте на несколько вопросов и зафиксируйте их в одном документе:
Если «краснеет» только один пункт, не делайте архитектурную революцию. Часто достаточно договориться о порогах, замерить базовую линию и оптимизировать узкие места.
Представьте B2B-кабинет: таблица на 2-5 тысяч строк (постранично), слева фильтры, сверху поиск, в строках быстрые действия (изменить статус, назначить менеджера, скачать акт). Пользователь много кликает и печатает, и его раздражают два типа задержек: ввод «залипает», а таблица перерисовывается целиком при каждом изменении.
При этом продукт живет релизами: каждую неделю добавляются новые поля, фильтры, роли, интеграции. Команде важна скорость изменений не меньше, чем идеальные миллисекунды.
Рантайм-тяжелый стек дает быстрый старт разработке за счет экосистемы и привычных практик, но чаще привозит больше работы в браузер. Компиляторный подход может быть заметно приятнее именно на «горячих» экранах с частыми обновлениями.
Практичный гибридный план обычно выглядит так: найти 1-2 самых нагруженных экрана, договориться о метриках отклика (задержка ввода, реакция на клик, плавность скролла), оставить общий стек ради скорости разработки, а горячие места сделать легче (компиляция или точечные оптимизации). Главное - проверять эффект на реальных данных и реальных устройствах.
Чтобы не спорить о фреймворках «в вакууме», превратите выбор в короткий тест. Заранее договоритесь, что вы считаете быстрым, и где это реально влияет на продукт.
Зафиксируйте 2-3 метрики и 3 сценария: холодный запуск до интерактивности, задержка ответа интерфейса на клик, плавность прокрутки в длинном списке. Затем соберите небольшой прототип одного ключевого экрана и сравните подходы на ваших данных, а не на демо.
Если вам нужно быстро собрать такой прототип и безопасно откатывать изменения по ходу экспериментов, это удобно делать в TakProsto (takprosto.ai): собрать экран в чате, делать снимки и rollback, а когда найдете рабочий вариант - экспортировать исходники и продолжить разработку в привычном процессе.
«Медленный» — это когда человек чувствует задержку:
Если пользователь начинает «промахиваться» по интерфейсу или ждать, для него сайт медленный, даже если отчёт по метрикам выглядит прилично.
Чаще всего виновата большая работа в главном потоке при запуске:
Практическое правило: если «всё видно», но клики не реагируют — это почти всегда перегрузка CPU на старте, а не «медленный сервер».
В рантайм-тяжёлом подходе вы привозите в браузер не только свой UI, но и общий «движок»: правила обновления, проверки, универсальные циклы, обвязку реактивности.
Платите обычно тремя вещами:
Иногда это оправдано экосистемой и скоростью разработки, но цену важно понимать заранее.
Идея в том, чтобы часть работы сделать до запуска в браузере, на этапе сборки.
Компилятор превращает шаблоны и реактивность в более прямой код: что именно поменять в DOM при изменении данных. В браузере меньше универсальной «служебной» логики, а обновления чаще становятся точечными.
Обычно это помогает там, где много частых обновлений: фильтры, таблицы, живой поиск, сложные формы.
Нет. Компиляция снижает накладные расходы фреймворка, но не отменяет базовые проблемы:
То есть компиляция может сделать обновления дешевле, но плохую архитектуру данных и UI не «исцелит» автоматически.
Начните с того, что реально ощущается:
Держите два слоя: лабораторные замеры для сравнения сборок и проверку на слабых устройствах/с ограничением CPU и сети.
Выберите 2–3 сценария, которые пользователи делают чаще всего, и сделайте их измеримыми. Например:
Дальше задайте пороги (например, «отклик на клик около 100 мс», «первый полезный экран за 2–3 секунды на среднем устройстве») и сравнивайте подходы на одних и тех же данных.
Если продукт зависит от «горячих» экранов с частыми обновлениями (таблицы, фильтры, дашборды), а аудитория часто на слабых устройствах — компиляция или более лёгкий рантайм дадут заметную пользу.
Если важнее скорость найма, готовые библиотеки, типовые паттерны, быстрые релизы — рантайм-тяжёлый стек может быть практичнее.
Хороший компромисс: оставить основной стек ради темпа, а 1–2 самых нагруженных экрана оптимизировать отдельно (архитектурно или технологически).
Самые частые ошибки:
Исправление почти всегда начинается с измерений и простого плана: что ускоряем, как проверяем, какие пороги считаем нормой.
Сделайте небольшой прототип одного ключевого экрана на ваших данных и сравните подходы по заранее выбранным метрикам.
Полезный минимальный план:
Если нужно быстро собирать такие прототипы и безопасно откатывать изменения, удобно использовать TakProsto: можно делать итерации через чат, сохранять снимки и делать rollback, а затем экспортировать исходники для дальнейшей разработки.