Обычно нам просто нужно написать HTML, CSS, JavaScript, чтобы отобразить красивую страницу на экране, но как браузер использует наш код для отображения пикселей на экране?
Браузер преобразует HTML, CSS и JavaScript в реальные пиксели, которые отображаются на экране.Серия шагов, которые браузеры проходят в течение этого периода, называется критическим путем рендеринга (Critical Rendering Path).
Рисунок 1-1 Конкретные этапы критического пути рендерингаНа рис. 1-1 показаны конкретные этапы критического пути рендеринга. Как показано, сначала браузер извлекает HTML и начинает строить DOM (объектная модель документа — объектная модель документа). Затем получите CSS и создайте CSSOM (объектная модель CSS — объектная модель CSS). Затем объедините DOM с CSSOM, чтобы создать дерево рендеринга. Затем найдите, где находится весь контент на веб-странице, что является шагом макета. Наконец, браузер начинает рисовать пиксели на экране.
При нормальных обстоятельствах браузер будет выполнять рендеринг с помощью шагов, описанных выше, но есть особый случай, когда JavaScript встречается при построении DOM, и ситуация становится другой. JavaScript влияет на процесс рендеринга, поэтому он является важной частью области производительности. Мы подробно обсудим этот частный случай позже. Давайте сначала обсудим, как построить DOM и CSSOM.
1. Создайте модель документа
Браузеры выполняют четко определенный набор шагов для обработки HTML и построения модели DOM. Макроскопически его можно разделить на несколько этапов. Как показано на рис. 1-2.
Рисунок 1-2 Конкретные шаги для построения DOMПервый шаг (преобразование): браузер считывает необработанные байты HTML с диска или сети и преобразует их на символы в соответствии с указанной кодировкой файла (например, UTF-8), как показано на рисунке 1-3.
Рисунок 1-3. Код байтового символа вВторой шаг (токенизация): преобразовать строку в токен, например: «», «
» и т. д. Маркер будет определять, является ли текущий маркер «начальным тегом», «конечным тегом» или «текстом», а также другую информацию. Рисунок 1-4 Преобразование строки в токенВ это время у вас должны возникнуть вопросы, как поддерживать отношения между узлами?
Фактически, это роль токена для идентификации «начального тега» и «конечного тега». Например, узел между начальным и конечным тегами токена «title» должен быть дочерним узлом «title». Как показано на рис. 1-5.
Рисунок 1-5 Связь между узламиРисунок 1-5 показывает взаимосвязь между узлами. Например, токен «Hello» расположен между начальным тегом «title» и конечным тегом «title», указывая, что токен «Hello» является дочерним узлом «title». "Жетон. Точно так же токен «title» является дочерним узлом токена «head».
Третий шаг (генерация узловых объектов и построение DOM): Фактически, в процессе построения DOM вместо ожидания преобразования всех токенов и последующего создания узловых объектов он потребляет токены при создании токенов для создания узловых объектов. Другими словами, после создания каждого токена он немедленно использует токен для создания объекта узла.
Токен с идентификатором конечного тега не создает объект узла
Объект узла содержит все свойства этого узла. Например<img src="xxx.png" />
Объект узла, окончательно сгенерированный меткой, сохранит адрес изображения и другую информацию.
Затем отношения между узлами идентифицируются и связываются с помощью «начального тега» и «конечного тега». Наконец, когда все токены сгенерированы и использованы, мы получаем полное дерево DOM. Процесс создания DOM из токена показан на рис. 1-6.
Рисунок 1-6 Создание DOMНа рис. 1.6 на каждой пунктирной линии есть небольшое число, обозначающее конкретные этапы построения модели DOM. Видно, что первый сгенерированныйhtml
Token и использовать Token для созданияhtml
Объект узла. затем сгенерироватьhead
Токен и использование токена для созданияhead
объект node и связать его сhtml
в дочерних узлах объекта узла. затем сгенерироватьtitle
Токен и использование токена для созданияtitle
объект node и связать его сhead
в дочерних узлах объекта узла. последний сгенерированныйbody
Токен и использование токена для созданияbody
объект node и связать его сhtml
в дочерних узлах . Когда все токены израсходованы, мы получаем полное DOM-дерево.
Конкретная реализация построения DOM очень похожа на принцип компиляции шаблонов Vue.Если вы хотите узнать, как процесс построения DOM реализован в коде, вы можете прочитать мою предыдущую статью наСтатья о принципах компиляции шаблона Vue. Вы также можете рассчитывать на мою новую книгу, которая более подробная и тщательная, чем статья о принципах компиляции шаблонов Vue.
2. Создайте CSSOM
DOM захватывает содержимое страницы, но браузеру также необходимо знать, как отображается страница. Поэтому нужно построить CSSOM (объектная модель CSS — объектная модель CSS).
Процесс построения CSSOM очень похож на процесс построения DOM: когда браузер получает фрагмент CSS, первое, что ему нужно сделать, — это идентифицировать токен, затем построить узел и сгенерировать CSSOM. Как показано на рис. 2-1.
Рисунок 2-1 Конкретный процесс построения CSSOMПредположим, браузер получает следующий CSS:
body {font-size: 16px;}
p {color: red;}
p span {display:none;}
span {font-size: 14px;}
img {float: right;}
CSSOM, сгенерированный вышеуказанным CSS после ряда шагов, показан на рис. 2-2.
Рисунок 2-2 Процесс построения CSSOMИз рисунка также видно, чтоbody
Дочерние узлы узла наследуютbody
правила стиля (размер шрифта 16px). Это каскадное правило, и поэтому CSS называется CSS (каскадные таблицы стилей).
Здесь я хочу сделать отступление. HTML можно анализировать шаг за шагом. Не нужно ждать, пока будут построены все DOM перед построением CSSOM. Вместо этого при разборе HTML для построения DOM, если встречается CSS, CSSOM будет построен сразу, а можно и одновременно. Но CSS не работает, неполный CSS использовать нельзя, потому что каждое свойство CSS может изменить CSSOM, поэтому возникает такая проблема: предположим, первые несколько байтов CSS устанавливают размер шрифта равным16px
, а затем установите размер шрифта на14px
, то если вся CSSOM построена не полностью, окончательный CSSOM на самом деле будет неточным. Следовательно, перед переходом к следующему этапу он должен дождаться создания CSSOM.
Следовательно, скорость загрузки CSS и скорость построения CSSOM будут напрямую влиять на скорость рендеринга первого экрана, поэтому CSS по умолчанию считается ресурсом, блокирующим рендеринг.
3. Постройте дерево рендеринга
DOM содержит все содержимое страницы, а CSSOM содержит все стили страницы.Теперь нам нужно скомпоновать DOM и CSSOM в дерево рендеринга.
Предположим, теперь у нас есть этот фрагмент кода:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Demos</title>
<style>
body {font-size: 16px;}
p {color: red;}
p span {display:none;}
span {font-size: 14px;}
img {float: right;}
</style>
</head>
<body>
<p>Hello <span>berwin</span></p>
<span>Berwin</span>
<img src="https://p1.ssl.qhimg.com/t0195d63bab739ec084.png" />
</body>
</html>
Этот код в конечном итоге встраивается в дерево рендеринга, как показано на рис. 3-1.
Рисунок 3-1 Построение дерева рендерингаВажной особенностью дерева рендеринга является то, что он захватывает только видимое содержимое, и для построения дерева рендеринга браузеру необходимо сделать следующее:
- Корневой узел из дерева DOM начнет обход каждого видимого узла.
- Некоторые узлы не видны (например, токены скриптов, мета-токены и т. д.) и игнорируются, поскольку они не будут отражены в отображаемом выводе.
- Некоторые узлы скрыты CSS и поэтому также игнорируются в дереве рендеринга. Например: картинка выше
p > span
Узел не появится в дереве рендеринга, потому что узел установленdisplay: none
Атрибуты.
- Для каждого видимого узла найдите адаптированные для него правила CSSOM и примените их.
Таким образом, окончательный результат рендеринга показан на рисунке ниже.
Рисунок 3-2 Дерево рендеринга и результаты рендеринга4. Макет
Следующим шагом при работе с деревом рендеринга является переход к этапу компоновки. На этом этапе браузер должен определить точное местоположение и размер каждого узла на странице. Часто такое поведение также называют «автоперекомпоновкой».
Результатом процесса компоновки является «блочная модель», которая точно фиксирует точное положение и размер каждого элемента в окне просмотра, при этом все относительные измерения преобразуются в абсолютные пиксели на экране. Как показано на рис. 4-1.
Рисунок 4-1 Компоновка5. Рисовать
Сразу после завершения компоновки браузер генерирует события «Paint Setup» и «Paint» для преобразования дерева рендеринга в пиксели на экране. Как показано на рис. 5-1.
Рисунок 5-1 Чертеж6. JS и критический путь рендеринга
Теперь, возвращаясь к вопросу, оставленному в начале статьи, мы обсудили критический путь рендеринга, но предыдущее обсуждение не касалось JS. Это потому, что JS сломает то, что мы обсуждали ранее.
Все мы знаем, что загрузка, синтаксический анализ и выполнение JavaScript будет блокировать построение DOM, то есть когда анализатор HTML встречает JavaScript при построении DOM, он приостанавливает построение DOM, передавая управление JavaScript engine и дождитесь JavaScript. После завершения работы движка браузер возобновляет построение DOM с того места, где он остановился.
Поскольку JavaScript может изменять содержимое веб-страниц, он может изменить DOM. Если он не заблокирован, то DOM строится здесь, а DOM модифицируется JavaScript там. Как убедиться, что окончательный DOM правильный ? И в чем разница между DOM, полученным в первую секунду, и DOM, полученным в следующую секунду в JS? Это вызовет ряд проблем, поэтому JS блокирует процесс построения DOM, поэтому элементы, лежащие в основе JS, не могут быть получены в JS, потому что DOM еще не построен.
Влияние JavaScript на критический путь рендеринга не только блокирует построение DOM, но и вызываетCSSOM также блокирует построение DOM..
Первоначально построение DOM и CSSOM не влияли друг на друга, и колодезная вода не делала речную воду, однако после появления JavaScript CSSOM также стал блокировать построение DOM. Только после построения CSSOM DOM возобновил работу с DOM. строительство.
Что тут происходит?
Это связано с тем, что JavaScript может не только изменять DOM, но и изменять стили, что означает, что он может изменять CSSOM. Ранее мы сообщали, что неполный CSSOM нельзя использовать, но если вы хотите получить доступ к CSSOM и изменить его в JavaScript, вы должны иметь возможность получить полный CSSOM при выполнении JavaScript. Так что это приводит к явлению, если браузер не завершил загрузку и построение CSSOM, а мы хотим запустить скрипт в это время, то браузер отложит выполнение скрипта и построение DOM до тех пор, пока не завершит загрузку и построение CSSOM .
То есть в этом случае браузер загружает и строит CSSOM, затем выполняет JavaScript, а затем продолжает строить DOM.
Это вызовет серьезные проблемы с производительностью. Мы предполагаем, что для построения DOM требуется одна секунда, а для построения CSSOM — одна секунда. В обычных условиях для одновременного построения DOM и CSSOM требуется всего одна секунда, а затем переходим к следующий этап. Но если вводится JavaScript, то JavaScript блокирует построение DOM и ждет загрузки и сборки CSSOM через секунду, предполагая, что для выполнения JavaScript требуется0.00000001
секунд, то после возобновления построения ДОМа с прерванного места, потребуется еще секунда для завершения построения ДОМа, а для перехода на следующий этап требуется всего 2 секунды. Как показано на рис. 6-1.
Например, следующий код не загружает JS:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
<link rel="stylesheet" href="https://static.xx.fbcdn.net/rsrc.php/v3/y6/l/1,cross/9Ia-Y9BtgQu.css">
</head>
<body>
aa
</body>
</html>
Результат выполнения приведенного выше кода показан на рис. 6-2.
Рисунок 6-2 CSS не блокирует DOMСобытие DOMContentLoaded срабатывает примерно через 116 мс.
Добавьте JavaScript в код:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
<link rel="stylesheet" href="https://static.xx.fbcdn.net/rsrc.php/v3/y6/l/1,cross/9Ia-Y9BtgQu.css">
</head>
<body>
aa
<script>
console.log(1)
</script>
</body>
</html>
Событие DOMContentLoaded срабатывает через 1,21 с, как показано на рис. 6-3.
Рисунок 6-3 CSS, блокирующий DOM7. Резюме
Критический путь рендеринга (Critical Rendering Path) относится к серии шагов, которые браузеры проходят для преобразования HTML, CSS и JavaScript в реальные пиксели, отображаемые на экране.
Критический путь рендеринга состоит из пяти шагов. Построить DOM -> Построить CSSOM -> Построить дерево рендеринга -> Макет -> Рисовать.
CSSOM заблокирует рендеринг, и только когда CSSOM будет построен, он перейдет к следующему этапу построения дерева рендеринга.
Обычно DOM и CSSOM строятся параллельно, но когда браузер сталкивается сscript
тег, построение DOM будет приостановлено до тех пор, пока скрипт не завершит выполнение. Однако, поскольку JavaScript может модифицировать CSSOM, необходимо дождаться создания CSSOM перед выполнением JS.
Адрес моего блога:GitHub.com/Не Эрвин/блог…