Какие этапы рендера страницы в браузере начиная с получения первых килобайт HTML
Что проверяют
Знаете ли вы, что браузер не ждёт весь документ, а работает потоково, и что именно задерживает первую отрисовку. Следом спрашивают про разницу async и defer или про то, почему стили в конце документа это плохая идея.
Как отвечать
Рассказывайте как поток событий, а не как список терминов:
- байты в символы: кодировка берётся из
Content-Typeили из<meta charset>, который должен стоять в первых 1024 байтах, иначе браузер может начать разбор заново; - токенизация и DOM: парсер строит дерево по мере прихода данных, первые килобайты уже превращаются в узлы;
- preload scanner: просматривает разметку вперёд и заранее запрашивает стили, скрипты и картинки, даже пока основной парсер стоит;
- стили: каждый
<link rel="stylesheet">блокирует отрисовку до готовности CSSOM, а цепочка@importдобавляет лишние сетевые круги; - скрипты: обычный
<script>останавливает парсер и ждёт ещё и загрузки CSS выше себя, ведь он может читать стили.deferвыполняется после разбора в порядке следования,asyncсразу по загрузке в любом порядке,type="module"ведёт себя какdefer; - первый кадр: когда есть DOM до текущего места и готовые стили, браузер считает стили, раскладку, рисует и показывает первый контент (FCP), не дожидаясь конца HTML.
Практический вывод: из-за начального окна перегрузки TCP за первый круг приходит около 14 КБ, поэтому критичные стили и разметку первого экрана выгодно уложить в начало ответа. Сервер может отдать <head> стримингом, ещё до того как собрал тело, а ответ 103 Early Hints запускает загрузку ресурсов, пока бэкенд думает.
Где спотыкаются
Считают, что рендер начинается после загрузки всего HTML. Отсюда непонимание, зачем нужны ранний флаш <head> и стриминг.
Путают async и defer и ставят async скриптам, зависящим друг от друга. Порядок выполнения ломается, и ошибка всплывает только на медленной сети.
Прячут важные картинки за JavaScript или CSS-фоном. Preload scanner их не видит, загрузка стартует на несколько кругов позже, и страдает LCP.