Learning Book

Critical Rendering Path

Critical Rendering Path

Этапы построения страницы

Когда браузер получает HTML, он проходит следующие этапы:

HTML → DOM → ┐
              ├─ Render Tree → Layout → Paint → Composite
CSS → CSSOM → ┘

1. Parsing HTML → DOM: браузер токенизирует HTML и строит дерево DOM-узлов.

2. Parsing CSS → CSSOM: все CSS правила компилируются в дерево CSSOM (CSS Object Model).

3. Render Tree: DOM + CSSOM объединяются. Исключаются display: none элементы и <head>.

4. Layout (Reflow): браузер вычисляет геометрию — размеры и позиции всех элементов.

5. Paint: браузер рисует пиксели — цвета, тексты, изображения.

6. Composite: браузер объединяет слои (layers) в финальное изображение.

Что блокирует рендеринг

<!-- CSS блокирует рендеринг — браузер ждёт загрузки -->
<link rel="stylesheet" href="styles.css">

<!-- JS по умолчанию блокирует парсинг HTML -->
<script src="app.js"></script>

<!-- НЕ блокирует парсинг HTML -->
<script src="app.js" defer></script>
<script src="app.js" async></script>

<!-- Не блокирует рендеринг (только медиа нужного типа) -->
<link rel="stylesheet" href="print.css" media="print">
defer — скрипт загружается параллельно, выполняется после парсинга DOM, в порядке в документе. async — загружается параллельно, выполняется немедленно после загрузки (порядок не гарантирован). Используйте defer для большинства скриптов.

Compositor Layers — быстрые анимации

Некоторые свойства CSS анимируются без Layout и Paint — только Composite:

/* Эти свойства — только Composite (GPU, быстро): */
transform: translate/scale/rotate
opacity

/* Эти свойства — вызывают Paint (медленнее): */
color, background, box-shadow, border

/* Эти свойства — вызывают Layout + Paint (самые медленные): */
width, height, top, left, margin, padding
// МЕДЛЕННО: вызывает layout
element.style.left = position + 'px'

// БЫСТРО: только composite (GPU)
element.style.transform = `translateX(${position}px)`
/* Создаём отдельный layer заранее (GPU) */
.animated-element {
  will-change: transform; /* браузер заранее создаёт layer */
}

/* Осторожно! Каждый layer — дополнительная память GPU */
/* Не применяйте will-change ко всем элементам */

Также: transform: translateZ(0) или transform: translate3d(0,0,0) — старый хак для создания GPU layer (но will-change предпочтительнее).