Как рендерится страница в браузере с момента получения ответа
Что проверяют
Знаете ли вы критический путь рендеринга настолько, чтобы объяснить, почему страница долго остаётся белой и откуда рывки при скролле. Следом обычно спрашивают, что блокирует рендер, чем async отличается от defer и какие свойства дешевле анимировать.
Как отвечать
Идите по конвейеру от первых байтов ответа:
- HTML: разбирается потоково, по мере прихода данных, и строит DOM. Параллельно preload scanner находит ссылки на CSS, скрипты и картинки и заранее ставит их в загрузку;
- CSS: превращается в CSSOM и блокирует рендер. Пока стили из
<head>не загружены, браузер не рисует, иначе вы увидели бы вспышку нестилизованного контента; - JavaScript: обычный
<script>останавливает парсер и перед выполнением ждёт CSS, подключённый выше.deferвыполняется после разбора документа по порядку,asyncсразу по готовности, модули ведут себя какdefer; - style: вычисляются итоговые стили узлов. В дерево отрисовки не попадает
display: none, аvisibility: hiddenпопадает и занимает место; - layout: размеры и позиции. Сдвиг одного блока задевает соседей, поэтому этап дорогой;
- paint: заполнение слоёв пикселями: текст, фоны, тени;
- composite: сборка слоёв в кадр, часто на GPU.
transformиopacityменяются только здесь, поэтому их и анимируют.
После первой отрисовки конвейер повторяется частично: смена width запускает layout, paint и composite, смена цвета только paint и composite. Чтение offsetHeight сразу после записи стиля заставляет браузер синхронно пересчитать layout, отсюда layout thrashing в циклах.
Свяжите это с метриками: FCP и LCP упираются в блокирующие CSS и JS, CLS в сдвиги layout, INP в долгие задачи главного потока.
Где спотыкаются
Описывают этапы строго по очереди: скачали весь HTML, потом CSS, потом JS. На деле разбор потоковый, загрузки параллельные, и первая отрисовка случается до конца документа.
Говорят, что скрытые элементы не попадают в дерево рендера, без уточнений. Это верно только для display: none.
Считают любую анимацию одинаково дорогой. Анимация top или height гоняет layout на каждом кадре, а transform нет.