\n \n\n\n// Результат парсинга - DOM дерево\nDocument\n html\n head\n title \"Страница\"\n link\n body\n header \"Заголовок\"\n main\n h1 \"Контент\"\n p \"Описание\"\n```\n\n### 2. Loading Resources (Загрузка ресурсов)\n\nПаралельно с парсингом браузер загружает внешние ресурсы:\n- CSS файлы\n- JavaScript файлы (блокирующие)\n- Изображения\n- Шрифты\n\n```javascript\n// Критический путь загрузки (Critical Rendering Path)\n1. HTML парсинг -> Download CSS -> Parse CSS -> Download JS -> Execute JS -> Render\n\n// Оптимизация критического пути\n\n \n \n \n \n\n\n\n \n \n \n \n \n \n\n```\n\n### 3. CSSOM Construction (Построение CSSOM дерева)\n\nБраузер создаёт CSS Object Model дерево:\n\n```javascript\n// CSS файл\nbody { font-family: Arial; }\nh1 { color: blue; font-size: 24px; }\n.container { display: flex; gap: 10px; }\n\n// CSSOM дерево\nStyleSheetList\n StyleSheet\n CSSStyleRule\n selectorText: \"body\"\n style: { fontFamily: \"Arial\" }\n CSSStyleRule\n selectorText: \"h1\"\n style: { color: \"blue\", fontSize: \"24px\" }\n CSSStyleRule\n selectorText: \".container\"\n style: { display: \"flex\", gap: \"10px\" }\n```\n\n### 4. Render Tree Construction (Построение дерева рендеринга)\n\nКомбинация DOM и CSSOM создаёт Render Tree:\n\n```javascript\n// Render Tree содержит только видимые элементы\n// Элементы с display: none или visibility: hidden исключены\n\nRender Tree\n body (display: block)\n header (display: block)\n text: \"Заголовок\"\n main (display: block)\n h1 (display: block, color: blue)\n text: \"Контент\"\n p (display: block)\n text: \"Описание\"\n\n// Каждый элемент в Render Tree знает свои стили из CSSOM\n```\n\n### 5. Layout (Макетирование)\n\nБраузер вычисляет позицию и размер каждого элемента:\n\n```javascript\n// Layout вычисляет координаты и размеры\n// Процесс называется \"reflow\"\n\nbody\n x: 0, y: 0, width: 1024, height: 768\n header\n x: 0, y: 0, width: 1024, height: 60\n main\n x: 0, y: 60, width: 1024, height: 708\n h1\n x: 16, y: 76, width: 992, height: 32\n p\n x: 16, y: 108, width: 992, height: 20\n\n// Избегай принудительного reflow\n// Плохо: множественные обращения к offsetWidth\nconst width = element.offsetWidth\nelement.style.width = (width + 10) + 'px'\nconst newWidth = element.offsetWidth\n\n// Хорошо: читай один раз, потом пиши\nconst width = element.offsetWidth\nelement.style.width = (width + 10) + 'px'\n```\n\n### 6. Painting (Окрашивание)\n\nБраузер преобразует каждый пиксель Render Tree в пиксели:\n\n```javascript\n// Paint создаёт слои (layers) для оптимизации\n// Каждый слой отрисовывается отдельно\n\nLayers\n Layer 1: background\n Paint body background color\n Layer 2: text\n Paint \"Заголовок\" текст\n Paint \"Контент\" текст\n Paint \"Описание\" текст\n Layer 3: borders\n Paint borders элементов\n\n// Минимизируй paint операции\n// Избегай изменения background-color часто\ndocument.addEventListener('mousemove', () => {\n // Плохо - триггер paint при каждом движении мыши\n element.style.backgroundColor = getRandomColor()\n})\n\n// Хорошо - используй requestAnimationFrame для batch обновлений\nlet pendingPaint = false\ndocument.addEventListener('mousemove', () => {\n if (!pendingPaint) {\n pendingPaint = true\n requestAnimationFrame(() => {\n element.style.backgroundColor = getRandomColor()\n pendingPaint = false\n })\n }\n})\n```\n\n### 7. Compositing (Композитирование)\n\nБраузер объединяет слои в финальное изображение:\n\n```javascript\n// Compositing происходит в GPU для производительности\n// CSS свойства, вызывающие compositing:\ntransform: translate(0, 0)\nopacity: 0.5\nwill-change: transform\n\n// Хорошая практика для анимаций\n.animated {\n will-change: transform;\n animation: slide 0.3s ease-out;\n}\n\n@keyframes slide {\n from { transform: translateX(-100px); }\n to { transform: translateX(0); }\n}\n```\n\n## Core Web Vitals и рендеринг\n\n```javascript\n// Метрики производительности, связанные с рендерингом\n\n// 1. First Contentful Paint (FCP) - первый видимый контент\nconst observer = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n console.log('FCP:', entry.startTime)\n }\n})\nobserver.observe({ entryTypes: ['paint'] })\n\n// 2. Largest Contentful Paint (LCP) - самый большой элемент\nconst lcpObserver = new PerformanceObserver((list) => {\n const entries = list.getEntries()\n const lastEntry = entries[entries.length - 1]\n console.log('LCP:', lastEntry.renderTime || lastEntry.loadTime)\n})\nlcpObserver.observe({ entryTypes: ['largest-contentful-paint'] })\n\n// 3. Cumulative Layout Shift (CLS) - непредвиденные сдвиги макета\nlet clsValue = 0\nconst clsObserver = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n if (!entry.hadRecentInput) {\n clsValue += entry.value\n }\n }\n console.log('CLS:', clsValue)\n})\nclsObserver.observe({ entryTypes: ['layout-shift'] })\n```\n\n## Оптимизация рендеринга\n\n```javascript\n// 1. Минимизируй layout thrashing\n// Плохо\nfor (let i = 0; i < items.length; i++) {\n items[i].style.width = items[i].offsetWidth + 10 + 'px'\n}\n\n// Хорошо\nconst widths = items.map(item => item.offsetWidth)\nitems.forEach((item, i) => {\n item.style.width = (widths[i] + 10) + 'px'\n})\n\n// 2. Используй requestAnimationFrame для анимаций\nfunction animate() {\n element.style.transform = `translateX(${position}px)`\n position += 5\n if (position < 200) {\n requestAnimationFrame(animate)\n }\n}\nrequestAnimationFrame(animate)\n\n// 3. Кэшируй селекторы DOM\nconst elements = document.querySelectorAll('.item')\n// Используй elements, не запрашивай снова\nelements.forEach(el => {\n el.classList.add('active')\n})\n\n// 4. Используй CSS при возможности вместо JavaScript\n// Плохо - JS анимация\nsetInterval(() => {\n element.style.opacity = Math.random()\n}, 16)\n\n// Хорошо - CSS анимация\nelement.style.animation = 'fadeInOut 2s infinite'\n```\n\n## Инструменты для анализа\n\n```javascript\n// Chrome DevTools Performance\n// Позволяет увидеть timeline всего процесса рендеринга\n\n// Lighthouse оценивает производительность\n// Web Vitals библиотека для мониторинга метрик\n\nimport { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals'\n\ngetFCP(metric => console.log('FCP:', metric))\ngetLCP(metric => console.log('LCP:', metric))\ngetCLS(metric => console.log('CLS:', metric))\n```","dateCreated":"2026-04-03T17:54:42.047424","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как прокинуть ссылку в дочерний React компонент?

2.0 Middle🔥 181 комментариев
#React

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Процесс рендеринга HTML-страницы

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

Основные этапы рендеринга

1. Parsing (Парсинг)

Браузер парсит HTML и создаёт DOM дерево:

// HTML
<html>
  <head>
    <title>Страница</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <header>Заголовок</header>
    <main>
      <h1>Контент</h1>
      <p>Описание</p>
    </main>
    <script src="app.js"></script>
  </body>
</html>

// Результат парсинга - DOM дерево
Document
  html
    head
      title "Страница"
      link
    body
      header "Заголовок"
      main
        h1 "Контент"
        p "Описание"

2. Loading Resources (Загрузка ресурсов)

Паралельно с парсингом браузер загружает внешние ресурсы:

  • CSS файлы
  • JavaScript файлы (блокирующие)
  • Изображения
  • Шрифты
// Критический путь загрузки (Critical Rendering Path)
1. HTML парсинг -> Download CSS -> Parse CSS -> Download JS -> Execute JS -> Render

// Оптимизация критического пути
<head>
  <!-- Сразу нужный CSS -->
  <link rel="stylesheet" href="critical.css" media="screen">
  <!-- Отложенный CSS -->
  <link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">
</head>

<body>
  <!-- JS в конце, чтобы не блокировать парсинг -->
  <script src="app.js"></script>
  <!-- Или асинхронно -->
  <script src="analytics.js" async></script>
  <!-- Или отложенно -->
  <script src="interactive.js" defer></script>
</body>

3. CSSOM Construction (Построение CSSOM дерева)

Браузер создаёт CSS Object Model дерево:

// CSS файл
body { font-family: Arial; }
h1 { color: blue; font-size: 24px; }
.container { display: flex; gap: 10px; }

// CSSOM дерево
StyleSheetList
  StyleSheet
    CSSStyleRule
      selectorText: "body"
      style: { fontFamily: "Arial" }
    CSSStyleRule
      selectorText: "h1"
      style: { color: "blue", fontSize: "24px" }
    CSSStyleRule
      selectorText: ".container"
      style: { display: "flex", gap: "10px" }

4. Render Tree Construction (Построение дерева рендеринга)

Комбинация DOM и CSSOM создаёт Render Tree:

// Render Tree содержит только видимые элементы
// Элементы с display: none или visibility: hidden исключены

Render Tree
  body (display: block)
    header (display: block)
      text: "Заголовок"
    main (display: block)
      h1 (display: block, color: blue)
        text: "Контент"
      p (display: block)
        text: "Описание"

// Каждый элемент в Render Tree знает свои стили из CSSOM

5. Layout (Макетирование)

Браузер вычисляет позицию и размер каждого элемента:

// Layout вычисляет координаты и размеры
// Процесс называется "reflow"

body
  x: 0, y: 0, width: 1024, height: 768
  header
    x: 0, y: 0, width: 1024, height: 60
  main
    x: 0, y: 60, width: 1024, height: 708
    h1
      x: 16, y: 76, width: 992, height: 32
    p
      x: 16, y: 108, width: 992, height: 20

// Избегай принудительного reflow
// Плохо: множественные обращения к offsetWidth
const width = element.offsetWidth
element.style.width = (width + 10) + 'px'
const newWidth = element.offsetWidth

// Хорошо: читай один раз, потом пиши
const width = element.offsetWidth
element.style.width = (width + 10) + 'px'

6. Painting (Окрашивание)

Браузер преобразует каждый пиксель Render Tree в пиксели:

// Paint создаёт слои (layers) для оптимизации
// Каждый слой отрисовывается отдельно

Layers
  Layer 1: background
    Paint body background color
  Layer 2: text
    Paint "Заголовок" текст
    Paint "Контент" текст
    Paint "Описание" текст
  Layer 3: borders
    Paint borders элементов

// Минимизируй paint операции
// Избегай изменения background-color часто
document.addEventListener('mousemove', () => {
  // Плохо - триггер paint при каждом движении мыши
  element.style.backgroundColor = getRandomColor()
})

// Хорошо - используй requestAnimationFrame для batch обновлений
let pendingPaint = false
document.addEventListener('mousemove', () => {
  if (!pendingPaint) {
    pendingPaint = true
    requestAnimationFrame(() => {
      element.style.backgroundColor = getRandomColor()
      pendingPaint = false
    })
  }
})

7. Compositing (Композитирование)

Браузер объединяет слои в финальное изображение:

// Compositing происходит в GPU для производительности
// CSS свойства, вызывающие compositing:
transform: translate(0, 0)
opacity: 0.5
will-change: transform

// Хорошая практика для анимаций
.animated {
  will-change: transform;
  animation: slide 0.3s ease-out;
}

@keyframes slide {
  from { transform: translateX(-100px); }
  to { transform: translateX(0); }
}

Core Web Vitals и рендеринг

// Метрики производительности, связанные с рендерингом

// 1. First Contentful Paint (FCP) - первый видимый контент
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log('FCP:', entry.startTime)
  }
})
observer.observe({ entryTypes: ['paint'] })

// 2. Largest Contentful Paint (LCP) - самый большой элемент
const lcpObserver = new PerformanceObserver((list) => {
  const entries = list.getEntries()
  const lastEntry = entries[entries.length - 1]
  console.log('LCP:', lastEntry.renderTime || lastEntry.loadTime)
})
lcpObserver.observe({ entryTypes: ['largest-contentful-paint'] })

// 3. Cumulative Layout Shift (CLS) - непредвиденные сдвиги макета
let clsValue = 0
const clsObserver = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (!entry.hadRecentInput) {
      clsValue += entry.value
    }
  }
  console.log('CLS:', clsValue)
})
clsObserver.observe({ entryTypes: ['layout-shift'] })

Оптимизация рендеринга

// 1. Минимизируй layout thrashing
// Плохо
for (let i = 0; i < items.length; i++) {
  items[i].style.width = items[i].offsetWidth + 10 + 'px'
}

// Хорошо
const widths = items.map(item => item.offsetWidth)
items.forEach((item, i) => {
  item.style.width = (widths[i] + 10) + 'px'
})

// 2. Используй requestAnimationFrame для анимаций
function animate() {
  element.style.transform = `translateX(${position}px)`
  position += 5
  if (position < 200) {
    requestAnimationFrame(animate)
  }
}
requestAnimationFrame(animate)

// 3. Кэшируй селекторы DOM
const elements = document.querySelectorAll('.item')
// Используй elements, не запрашивай снова
elements.forEach(el => {
  el.classList.add('active')
})

// 4. Используй CSS при возможности вместо JavaScript
// Плохо - JS анимация
setInterval(() => {
  element.style.opacity = Math.random()
}, 16)

// Хорошо - CSS анимация
element.style.animation = 'fadeInOut 2s infinite'

Инструменты для анализа

// Chrome DevTools Performance
// Позволяет увидеть timeline всего процесса рендеринга

// Lighthouse оценивает производительность
// Web Vitals библиотека для мониторинга метрик

import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals'

getFCP(metric => console.log('FCP:', metric))
getLCP(metric => console.log('LCP:', metric))
getCLS(metric => console.log('CLS:', metric))