> Почему ресурсы CSS и JavaScript блокируют построение и отображение страницы (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Rutube
Стек: JavaScript
> Пример ответа
Короткий ответ
CSS и JavaScript блокируют построение и отображение страницы, потому что браузер обрабатывает их синхронно в критическом пути рендеринга. CSS блокирует рендеринг, так как браузер не показывает частично стилизованный контент (flash of unstyled content). JavaScript блокирует построение DOM, поскольку может изменять DOM и CSSOM, и браузер приостанавливает парсинг HTML до полного выполнения скрипта.
Подробное объяснение
Критический путь рендеринга состоит из нескольких этапов: парсинг HTML в DOM, парсинг CSS в CSSOM, объединение в render tree, layout и paint. CSS и JavaScript влияют на этот процесс следующим образом:
CSS (CSSOM):
- CSS считается render-blocking ресурсом: браузер не начинает рендеринг, пока не построит CSSOM полностью.
- Это сделано для предотвращения FOUC (flash of unstyled content) - пользователь не должен видеть страницу без стилей.
- CSSOM строится синхронно: пока не загружен и не распарсен весь CSS, браузер не переходит к следующему шагу.
JavaScript (DOM):
- По умолчанию
<script>без атрибутовasyncилиdeferявляется parser-blocking: браузер останавливает парсинг HTML, загружает и выполняет скрипт, и только потом продолжает. - Это необходимо, так как скрипт может:
- Изменять DOM (например,
document.write()) - Запрашивать стили (например,
getComputedStyle()), что требует готового CSSOM
- Изменять DOM (например,
- Если скрипт выполняется до завершения CSSOM, браузер блокирует его выполнение до загрузки CSS - это называется CSS-блокировка JavaScript.
Взаимодействие:
- Если JavaScript встречается до CSS, он может быть отложен до загрузки CSS (если скрипт запрашивает стили).
- Если CSS загружается после JavaScript, скрипт может выполняться, но рендеринг всё равно будет заблокирован до полной загрузки CSS.
На практике
Для оптимизации производительности загрузки страницы используются следующие подходы:
-
Критический CSS: встраивание минимального набора стилей для первого экрана непосредственно в
<head>через<style>, остальной CSS загружается асинхронно с помощьюmedia="print" onload="this.media='all'"или черезrel="preload". -
Асинхронная загрузка JavaScript:
async: скрипт загружается параллельно с парсингом HTML и выполняется сразу после загрузки, блокируя парсинг.defer: скрипт загружается параллельно, но выполняется только после завершения парсинга HTML, в порядке появления в документе.
-
Размещение скриптов в конце
<body>: классический подход, когда скрипты не блокируют построение DOM, но всё ещё блокируют рендеринг после выполнения. -
Preload и prefetch: для предварительной загрузки критических ресурсов (CSS, шрифты) с помощью
<link rel="preload">. -
Code splitting: разделение JavaScript на чанки, загружаемые по требованию (lazy loading).
Пример кода
HTML<!DOCTYPE html><html><head><!-- Критический CSS встроен --><style>body { font-family: sans-serif; margin: 0; padding: 20px; }.header { background: #333; color: white; padding: 10px; }</style><!-- Некритический CSS загружается асинхронно --><link rel="preload" href="styles.css" as="style" onload="this.rel='stylesheet'"><noscript><link rel="stylesheet" href="styles.css"></noscript><!-- Defer - выполнится после парсинга HTML --><script src="app.js" defer></script><!-- Async - выполнится сразу после загрузки, не гарантирует порядок --><script src="analytics.js" async></script></head><body><div class="header">Заголовок</div><p>Контент страницы</p><!-- Скрипты в конце body - классический подход --><script src="non-critical.js"></script></body></html>
Как отвечать на собеседовании
Начни с краткого определения критического пути рендеринга. Объясни, что CSS блокирует рендеринг из-за необходимости полного CSSOM, а JavaScript - парсинг DOM из-за возможных модификаций. Упомяни разницу между render-blocking и parser-blocking. Приведи примеры оптимизаций: critical CSS, async/defer, preload. Покажи понимание компромиссов: async нарушает порядок выполнения, defer задерживает выполнение до конца парсинга. Если спросят про метрики, свяжи с First Paint, First Contentful Paint и Time to Interactive.
Что проверяет интервьюер
- Понимание критического пути рендеринга и его этапов
- Знание разницы между DOM и CSSOM и их влияния на рендеринг
- Умение объяснять, почему браузер блокирует рендеринг (FOUC, консистентность)
- Практические навыки оптимизации загрузки (critical CSS, async/defer, preload)
- Понимание компромиссов между производительностью и функциональностью
Типичные ошибки
- Путать render-blocking (CSS) и parser-blocking (JavaScript) - это разные механизмы
- Считать, что
asyncиdeferполностью решают проблему блокировки - они влияют только на парсинг HTML, но не на рендеринг - Не учитывать, что JavaScript может быть заблокирован CSS (CSS-блокировка скриптов)
- Предлагать встраивать весь CSS в
<head>- это увеличивает размер HTML и время первого байта - Игнорировать влияние шрифтов и изображений на рендеринг (они тоже могут блокировать paint)
> Похожие задачи по frontend
Можно ли читать cookies из клиентского JavaScript
Для чего используется метод reverse у массивов в JavaScript
Как работают классы в JavaScript?
Являются ли функции объектами в JavaScript?
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью