Critical Rendering Path это последовательность шагов по превращению браузером HTML, CSS и JavaScript в пиксели на экране.

Итак, браузер получает на обработку HTML-файл. Парсер проходит его байт за байтом и вычленяет токены (самые главные - startTag, endTag), потом из набора токенов строятся ноды, а из иерархии нод получается Document Object Model (DOM) на основе информации о последовательности токенов. В DOM содержится весь контент страницы.

Когда парсер находит токены запросов внешних ресурсов (стилей, картинок, скриптов), он их запрашивает, но от 4 до 7 за раз в зависимости от браузера. Некоторые запросы блокируют парсинг, некоторые могут идти в параллели.

Когда парсер видит токен стилей, он начинает строить CSS Object Model (CSSOM). Оно строится очень быстро, поэтому оптимизация CSS-селекторов не даёт большого прироста к производительности, а минификация и отложенный запрос второстепенных стилей - даёт. Когда DOM и CSSOM готовы, начинается создание Render Tree.

Render Tree содержит в себе весь контент и его стилизацию. Кроме явно скрытых (display:none) элементов.

Эти три фазы, как правило,происходят один раз, но возможны ситуации когда свежезагруженный скрипт основательно меняет DOM (размеры элементов, отступы), тогда этот процесс происходит заново.

На основе Render Tree строится Layout - расположение элементов друг относительно друга и размеры блоков на основе их содержимого. Нужно помнить, что изменение размеров окна браузера, поворот смартфона, а и иногда и обычный запрос из скрипта расстояния между элементами может привести к пересчёту всего Layout. Чем больше DOM, тем больше занимает время пересчёт Layout (reflow). В это время страница не может реагировать на действия пользователя. Желательно что бы reflow занимал максимум 10 миллисекунд чтобы добиться 60 кадров в секунду.

Следующий шаг - Paint. Обычно он не доставляет хлопот в оптимизации, он просто растеризует (превращает в пиксели с помощью GPU) то, что насчиталось в Layout. Paint происходит в несколько слоёв в зависимости от позиционирования элементов. Проблемы с ним бывают при работе со сложной анимацией в canvas, они решаются отрисовкой в памяти, "за экраном" с помощью OffScreenCanvas или WebWorker-ов.

Поскольку отрисовка многослойная, мы получаем возможность двигать элементы не вызывая Paint снова. Пока только два стиля - opacity и transition - работают на этом этапе. Указать парсеру что элемент будет двигаться можно заранее с помощью

will-change: transform;

но не нужно делать этого повсеместно чтобы не нагружать GPU.

Поскольку браузер - основная платформа веб-разработчиков, непонимание вышеописанного процесса ведёт к созданию неотзывчивых сайтов.

Секунды задержки в интернет-магазинах приводят к миллионам недополученной прибыли. А из-за отсутствия при старте проекта требований к производительности, веб-приложение для гос-служащих с 15Мб скриптов на Камчатке грузится 38 минут.

Источники:

Личный опыт

https://developers.google.com/web/fundamentals/performance/rendering

https://developer.mozilla.org/en-US/docs/Web/Performance/Critical_rendering_path