Внутренняя работа процесса рендеринга
Это третья часть из четырех серий блогов, посвященная тому, как работают браузеры. Ранее мы рассмотрели многопроцессную архитектуру и поток навигации . В этом посте мы рассмотрим, что происходит внутри процесса рендеринга.
Процесс рендеринга затрагивает многие аспекты веб-производительности. Поскольку внутри процесса рендеринга происходит много всего, эта статья представляет собой лишь общий обзор. Если вы хотите копнуть глубже, в разделе «Производительность» раздела «Основы веб-технологий» есть гораздо больше ресурсов.
Процессы рендеринга обрабатывают веб-содержимое
Процесс рендеринга отвечает за все, что происходит внутри вкладки. В процессе рендеринга основной поток обрабатывает большую часть кода, который вы отправляете пользователю. Иногда части вашего JavaScript обрабатываются рабочими потоками, если вы используете веб-воркера или сервис-воркера. Потоки компоновщика и растра также запускаются внутри процессов рендеринга для эффективного и плавного рендеринга страницы.
Основная задача процесса рендеринга — превратить HTML, CSS и JavaScript в веб-страницу, с которой пользователь может взаимодействовать.

Разбор
Строительство ДОМ
Когда процесс рендеринга получает сообщение фиксации для навигации и начинает получать данные HTML, основной поток начинает анализировать текстовую строку (HTML) и превращать ее в объектную модель документа ( DOM ).
DOM — это внутреннее представление страницы в браузере, а также структура данных и API, с которыми веб-разработчик может взаимодействовать через JavaScript.
Синтаксический анализ HTML-документа в DOM определяется стандартом HTML . Возможно, вы заметили, что передача HTML в браузер никогда не выдает ошибку. Например, отсутствие закрывающего тега </p>
является допустимым HTML. Ошибочная разметка типа Hi! <b>I'm <i>Chrome</b>!</i>
(тег b закрывается перед тегом i) рассматривается так, как если бы вы написали Hi! <b>I'm <i>Chrome</i></b><i>!</i>
. Это связано с тем, что спецификация HTML предназначена для корректной обработки этих ошибок. Если вам интересно, как это делается, вы можете прочитать раздел « Введение в обработку ошибок и странные случаи в синтаксическом анализаторе » спецификации HTML.
Загрузка субресурса
Веб-сайт обычно использует внешние ресурсы, такие как изображения, CSS и JavaScript. Эти файлы необходимо загрузить из сети или кэша. Основной поток может запрашивать их один за другим по мере их обнаружения во время анализа для построения DOM, но для ускорения параллельно запускается «сканер предварительной загрузки». Если в документе HTML есть такие элементы, как <img>
или <link>
, сканер предварительной загрузки просматривает токены, сгенерированные анализатором HTML, и отправляет запросы в сетевой поток в процессе браузера.

JavaScript может блокировать синтаксический анализ
Когда анализатор HTML находит тег <script>
, он приостанавливает анализ HTML-документа и должен загрузить, проанализировать и выполнить код JavaScript. Почему? потому что JavaScript может изменить форму документа, используя такие вещи, как document.write()
, который меняет всю структуру DOM ( обзор модели синтаксического анализа в спецификации HTML имеет красивую диаграмму). Вот почему анализатору HTML приходится ждать запуска JavaScript, прежде чем он сможет возобновить анализ HTML-документа. Если вам интересно, что происходит при выполнении JavaScript, команда V8 проводит обсуждения и сообщения в блогах по этому поводу .
Подсказка браузеру, как вы хотите загружать ресурсы
Существует множество способов, которыми веб-разработчики могут отправлять подсказки браузеру для правильной загрузки ресурсов. Если ваш JavaScript не использует document.write()
, вы можете добавить атрибут async
или defer
в тег <script>
. Затем браузер загружает и запускает код JavaScript асинхронно и не блокирует синтаксический анализ. Вы также можете использовать модуль JavaScript, если это удобно. <link rel="preload">
— способ сообщить браузеру, что ресурс определенно необходим для текущей навигации и вы хотели бы его загрузить как можно скорее. Подробнее об этом можно прочитать в статье «Приоритезация ресурсов – помощь браузера» .
Расчет стиля
Иметь DOM недостаточно, чтобы знать, как будет выглядеть страница, поскольку мы можем стилизовать элементы страницы с помощью CSS. Основной поток анализирует CSS и определяет вычисляемый стиль для каждого узла DOM. Это информация о том, какой стиль применяется к каждому элементу на основе селекторов CSS. Вы можете увидеть эту информацию в computed
разделе DevTools.

Даже если вы не предоставляете CSS, каждый узел DOM имеет вычисленный стиль. Тег <h1>
отображается больше, чем тег <h2>
, а поля определяются для каждого элемента. Это связано с тем, что в браузере имеется таблица стилей по умолчанию. Если вы хотите узнать, что представляет собой CSS по умолчанию в Chrome, вы можете посмотреть исходный код здесь .
Макет
Теперь процесс рендеринга знает структуру документа и стили для каждого узла, но этого недостаточно для рендеринга страницы. Представьте, что вы пытаетесь описать картину своему другу по телефону. «Там большой красный круг и маленький синий квадрат» недостаточно для того, чтобы ваш друг знал, как именно будет выглядеть картина.

Компоновка — это процесс поиска геометрии элементов. Основной поток проходит через DOM и вычисляемые стили и создает дерево макета, которое содержит такую информацию, как координаты xy и размеры ограничивающей рамки. Дерево макета может иметь структуру, аналогичную дереву DOM, но оно содержит только информацию, связанную с тем, что видно на странице. Если применяется display: none
, этот элемент не является частью дерева макета (однако элемент с visibility: hidden
находится в дереве макета). Аналогично, если применяется псевдоэлемент с содержимым типа p::before{content:"Hi!"}
, он включается в дерево макета, даже если его нет в DOM.

Определение макета страницы — сложная задача. Даже самый простой макет страницы, такой как расположение блоков сверху вниз, должен учитывать размер шрифта и место разрыва строки, поскольку это влияет на размер и форму абзаца; что затем влияет на то, где должен быть следующий абзац.
CSS может перемещать элемент в сторону, маскировать элемент переполнения и изменять направление письма. Вы можете себе представить, перед этим этапом макетирования стоит огромная задача. В Chrome над версткой работает целая команда инженеров. Если вы хотите узнать подробности их работы, несколько выступлений с конференции BlinkOn записаны и их довольно интересно посмотреть.
Краска

Иметь DOM, стиль и макет по-прежнему недостаточно для рендеринга страницы. Допустим, вы пытаетесь воспроизвести картину. Вы знаете размер, форму и расположение элементов, но вам все равно придется судить, в каком порядке вы их рисуете.
Например, для определенных элементов может быть установлен z-index
, в этом случае рисование в порядке элементов, записанных в HTML, приведет к неправильному рендерингу.

На этом этапе рисования основной поток проходит по дереву макета для создания записей рисования. Запись рисования — это запись процесса рисования, например «сначала фон, затем текст, затем прямоугольник». Если вы рисовали элемент <canvas>
с помощью JavaScript, этот процесс может быть вам знаком.

Обновление конвейера рендеринга обходится дорого
Самое важное, что нужно понимать в конвейере рендеринга, — это то, что на каждом этапе результат предыдущей операции используется для создания новых данных. Например, если что-то изменится в дереве макета, то порядок рисования необходимо заново сгенерировать для затронутых частей документа.
Если вы анимируете элементы, браузер должен выполнять эти операции между каждым кадром. Большинство наших дисплеев обновляют экран 60 раз в секунду (60 кадров в секунду); Анимация будет казаться человеческому глазу гладкой, когда вы перемещаете объекты по экрану в каждом кадре. Однако если анимация пропускает промежуточные кадры, страница будет выглядеть «дерганой».

Даже если ваши операции рендеринга идут в ногу с обновлением экрана, эти вычисления выполняются в основном потоке, а это означает, что они могут быть заблокированы, когда ваше приложение выполняет JavaScript.

Вы можете разделить операцию JavaScript на небольшие фрагменты и запланировать запуск в каждом кадре, используя requestAnimationFrame()
. Дополнительную информацию по этой теме см. в разделе Оптимизация выполнения JavaScript . Вы также можете запустить свой JavaScript в Web Workers, чтобы избежать блокировки основного потока.

Композитинг
Как бы вы нарисовали страницу?
Теперь, когда браузер знает структуру документа, стиль каждого элемента, геометрию страницы и порядок рисования, как он рисует страницу? Преобразование этой информации в пиксели на экране называется растеризацией.
Возможно, самым простым способом справиться с этой задачей было бы растрировать части внутри области просмотра. Если пользователь прокручивает страницу, переместите растровый фрейм и заполните недостающие части, растрируя еще больше. Вот как Chrome обрабатывал растеризацию, когда он был впервые выпущен. Однако современный браузер запускает более сложный процесс, называемый композицией.
Что такое композитинг
Композиция — это метод разделения частей страницы на слои, их растеризации по отдельности и объединения страницы в отдельный поток, называемый потоком компоновщика. Если произойдет прокрутка, поскольку слои уже растрированы, все, что нужно сделать, — это скомпоновать новый кадр. Анимации можно добиться таким же образом, перемещая слои и создавая новый кадр.
Вы можете увидеть, как ваш веб-сайт разделен на слои в DevTools, используя панель «Слои» .
Разделение на слои
Чтобы выяснить, какие элементы должны находиться в каких слоях, основной поток проходит через дерево макета, чтобы создать дерево слоев (эта часть называется «Обновить дерево слоев» на панели производительности DevTools). Если определенные части страницы, которые должны быть отдельным слоем (например, боковое меню), не получают его, вы можете намекнуть браузеру, используя атрибут will-change
в CSS.

У вас может возникнуть соблазн добавить слои к каждому элементу, но композиция из избыточного количества слоев может привести к более медленной работе, чем растрирование небольших частей страницы в каждом кадре, поэтому крайне важно измерить производительность рендеринга вашего приложения. Дополнительные сведения по этой теме см. в разделах «Придерживаться свойств только для композитора» и «Управление количеством слоев» .
Растр и композит вне основного потока
После того как дерево слоев создано и порядок рисования определен, основной поток передает эту информацию в поток набора текста. Затем поток наборщика растрирует каждый слой. Слой может быть большим, например, во всю длину страницы, поэтому поток наборщика делит его на фрагменты и отправляет каждый фрагмент в растровые потоки. Растровые потоки растеризуют каждый тайл и сохраняют их в памяти графического процессора.

Поток компоновщика может определять приоритеты различных растровых потоков, чтобы объекты в области просмотра (или поблизости) могли быть растрированы в первую очередь. Слой также имеет несколько фрагментов для разных разрешений, чтобы обрабатывать такие действия, как увеличение масштаба.
После растрирования тайлов поток компоновщика собирает информацию о тайлах, называемую четырехугольниками рисования, для создания кадра компоновщика .
Нарисуйте четверные | Содержит такую информацию, как расположение плитки в памяти и место на странице для ее рисования с учетом композиции страницы. |
Рамка композитора | Коллекция четырехугольников, представляющих собой рамку страницы. |
Затем кадр композитора передается процессу браузера через IPC. На этом этапе можно добавить еще один кадр композитора из потока пользовательского интерфейса для изменения пользовательского интерфейса браузера или из других процессов рендеринга для расширений. Эти кадры наборщика отправляются в графический процессор для отображения на экране. Если происходит событие прокрутки, поток наборщика создает еще один кадр наборщика для отправки в графический процессор.

Преимущество композитинга в том, что он выполняется без участия основного потока. Потоку композитора не нужно ждать расчета стиля или выполнения JavaScript. Вот почему компоновка только анимации считается лучшей для плавной работы. Если макет или покраску необходимо рассчитать заново, то придется задействовать основную нить.
Заворачивать
В этом посте мы рассмотрели конвейер рендеринга от анализа до композиции. Надеемся, теперь у вас есть возможность узнать больше об оптимизации производительности веб-сайта.
В следующем и последнем посте этой серии мы более подробно рассмотрим поток композитора и посмотрим, что происходит, когда вводится пользовательский ввод, например mouse move
и click
мышью.
Вам понравился пост? Если у вас есть какие-либо вопросы или предложения по поводу будущего поста, я буду рад услышать ваше мнение в разделе комментариев ниже или на @kosamari в Твиттере.
Далее: Ввод поступает в композитор
,Внутренняя работа процесса рендеринга
Это третья часть из четырех серий блогов, посвященная тому, как работают браузеры. Ранее мы рассмотрели многопроцессную архитектуру и поток навигации . В этом посте мы рассмотрим, что происходит внутри процесса рендеринга.
Процесс рендеринга затрагивает многие аспекты веб-производительности. Поскольку внутри процесса рендеринга происходит много всего, эта статья представляет собой лишь общий обзор. Если вы хотите копнуть глубже, в разделе «Производительность» раздела «Основы веб-технологий» есть гораздо больше ресурсов.
Процессы рендеринга обрабатывают веб-содержимое
Процесс рендеринга отвечает за все, что происходит внутри вкладки. В процессе рендеринга основной поток обрабатывает большую часть кода, который вы отправляете пользователю. Иногда части вашего JavaScript обрабатываются рабочими потоками, если вы используете веб-воркера или сервис-воркера. Потоки компоновщика и растра также запускаются внутри процессов рендеринга для эффективного и плавного рендеринга страницы.
Основная задача процесса рендеринга — превратить HTML, CSS и JavaScript в веб-страницу, с которой пользователь может взаимодействовать.

Разбор
Строительство ДОМ
Когда процесс рендеринга получает сообщение фиксации для навигации и начинает получать данные HTML, основной поток начинает анализировать текстовую строку (HTML) и превращать ее в объектную модель документа ( DOM ).
DOM — это внутреннее представление страницы в браузере, а также структура данных и API, с которыми веб-разработчик может взаимодействовать через JavaScript.
Синтаксический анализ HTML-документа в DOM определяется стандартом HTML . Возможно, вы заметили, что передача HTML в браузер никогда не выдает ошибку. Например, отсутствие закрывающего тега </p>
является допустимым HTML. Ошибочная разметка типа Hi! <b>I'm <i>Chrome</b>!</i>
(тег b закрывается перед тегом i) рассматривается так, как если бы вы написали Hi! <b>I'm <i>Chrome</i></b><i>!</i>
. Это связано с тем, что спецификация HTML предназначена для корректной обработки этих ошибок. Если вам интересно, как это делается, вы можете прочитать раздел « Введение в обработку ошибок и странные случаи в синтаксическом анализаторе » спецификации HTML.
Загрузка субресурса
Веб-сайт обычно использует внешние ресурсы, такие как изображения, CSS и JavaScript. Эти файлы необходимо загрузить из сети или кэша. Основной поток может запрашивать их один за другим по мере их обнаружения во время анализа для построения DOM, но для ускорения параллельно запускается «сканер предварительной загрузки». Если в HTML-документе есть такие элементы, как <img>
или <link>
, сканер предварительной загрузки просматривает токены, сгенерированные анализатором HTML, и отправляет запросы в сетевой поток в процессе браузера.

JavaScript может блокировать синтаксический анализ
Когда анализатор HTML находит тег <script>
, он приостанавливает анализ HTML-документа и должен загрузить, проанализировать и выполнить код JavaScript. Почему? потому что JavaScript может изменить форму документа, используя такие вещи, как document.write()
, который меняет всю структуру DOM ( обзор модели синтаксического анализа в спецификации HTML имеет красивую диаграмму). Вот почему анализатору HTML приходится ждать запуска JavaScript, прежде чем он сможет возобновить анализ HTML-документа. Если вам интересно, что происходит при выполнении JavaScript, команда V8 проводит обсуждения и сообщения в блогах по этому поводу .
Подсказка браузеру, как вы хотите загружать ресурсы
Существует множество способов, которыми веб-разработчики могут отправлять подсказки браузеру для правильной загрузки ресурсов. Если ваш JavaScript не использует document.write()
, вы можете добавить атрибут async
или defer
в тег <script>
. Затем браузер загружает и запускает код JavaScript асинхронно и не блокирует синтаксический анализ. Вы также можете использовать модуль JavaScript, если это удобно. <link rel="preload">
— способ сообщить браузеру, что ресурс определенно необходим для текущей навигации и вы хотели бы его загрузить как можно скорее. Подробнее об этом можно прочитать в статье «Приоритезация ресурсов – помощь браузера» .
Расчет стиля
Иметь DOM недостаточно, чтобы знать, как будет выглядеть страница, поскольку мы можем стилизовать элементы страницы с помощью CSS. Основной поток анализирует CSS и определяет вычисляемый стиль для каждого узла DOM. Это информация о том, какой стиль применяется к каждому элементу на основе селекторов CSS. Вы можете увидеть эту информацию в computed
разделе DevTools.

Даже если вы не предоставляете CSS, каждый узел DOM имеет вычисленный стиль. Тег <h1>
отображается больше, чем тег <h2>
, а поля определяются для каждого элемента. Это связано с тем, что в браузере имеется таблица стилей по умолчанию. Если вы хотите узнать, что представляет собой CSS по умолчанию в Chrome, вы можете посмотреть исходный код здесь .
Макет
Теперь процесс рендеринга знает структуру документа и стили для каждого узла, но этого недостаточно для рендеринга страницы. Представьте, что вы пытаетесь описать картину своему другу по телефону. «Там большой красный круг и маленький синий квадрат» недостаточно для того, чтобы ваш друг знал, как именно будет выглядеть картина.

Компоновка — это процесс поиска геометрии элементов. Основной поток проходит через DOM и вычисляемые стили и создает дерево макета, которое содержит такую информацию, как координаты xy и размеры ограничивающей рамки. Дерево макета может иметь структуру, аналогичную дереву DOM, но оно содержит только информацию, связанную с тем, что видно на странице. Если применяется display: none
, этот элемент не является частью дерева макета (однако элемент с visibility: hidden
находится в дереве макета). Аналогично, если применяется псевдоэлемент с содержимым типа p::before{content:"Hi!"}
, он включается в дерево макета, даже если его нет в DOM.

Определение макета страницы — сложная задача. Даже самый простой макет страницы, такой как расположение блоков сверху вниз, должен учитывать размер шрифта и место разрыва строки, поскольку это влияет на размер и форму абзаца; что затем влияет на то, где должен быть следующий абзац.
CSS может перемещать элемент в сторону, маскировать элемент переполнения и изменять направление письма. Вы можете себе представить, перед этим этапом макетирования стоит огромная задача. В Chrome над версткой работает целая команда инженеров. Если вы хотите узнать подробности их работы, несколько выступлений с конференции BlinkOn записаны и их довольно интересно посмотреть.
Краска

Иметь DOM, стиль и макет по-прежнему недостаточно для рендеринга страницы. Допустим, вы пытаетесь воспроизвести картину. Вы знаете размер, форму и расположение элементов, но вам все равно придется судить, в каком порядке вы их рисуете.
Например, для определенных элементов может быть установлен z-index
, в этом случае рисование в порядке элементов, записанных в HTML, приведет к некорректному рендерингу.

На этом этапе рисования основной поток проходит по дереву макета для создания записей рисования. Запись рисования — это запись процесса рисования, например «сначала фон, затем текст, затем прямоугольник». Если вы рисовали элемент <canvas>
с помощью JavaScript, этот процесс может быть вам знаком.

Обновление конвейера рендеринга обходится дорого
Самое важное, что нужно понимать в конвейере рендеринга, — это то, что на каждом этапе результат предыдущей операции используется для создания новых данных. Например, если что-то изменится в дереве макета, то порядок рисования необходимо заново сгенерировать для затронутых частей документа.
Если вы анимируете элементы, браузер должен выполнять эти операции между каждым кадром. Большинство наших дисплеев обновляют экран 60 раз в секунду (60 кадров в секунду); Анимация будет казаться человеческому глазу гладкой, когда вы перемещаете объекты по экрану в каждом кадре. Однако если анимация пропускает промежуточные кадры, страница будет выглядеть «дерганой».

Даже если ваши операции рендеринга идут в ногу с обновлением экрана, эти вычисления выполняются в основном потоке, а это означает, что они могут быть заблокированы, когда ваше приложение выполняет JavaScript.

Вы можете разделить операцию JavaScript на небольшие фрагменты и запланировать их выполнение в каждом кадре, используя requestAnimationFrame()
. Дополнительную информацию по этой теме см. в разделе Оптимизация выполнения JavaScript . Вы также можете запустить свой JavaScript в Web Workers, чтобы избежать блокировки основного потока.

Композитинг
Как бы вы нарисовали страницу?
Теперь, когда браузер знает структуру документа, стиль каждого элемента, геометрию страницы и порядок рисования, как он рисует страницу? Преобразование этой информации в пиксели на экране называется растеризацией.
Возможно, самым простым способом справиться с этой задачей было бы растрировать части внутри области просмотра. Если пользователь прокручивает страницу, переместите растровый фрейм и заполните недостающие части, растрируя еще больше. Вот как Chrome обрабатывал растеризацию, когда он был впервые выпущен. Однако современный браузер запускает более сложный процесс, называемый композицией.
Что такое композитинг
Композиция — это метод разделения частей страницы на слои, их растеризации по отдельности и объединения страницы в отдельный поток, называемый потоком компоновщика. Если произойдет прокрутка, поскольку слои уже растрированы, все, что нужно сделать, — это скомпоновать новый кадр. Анимации можно добиться таким же образом, перемещая слои и создавая новый кадр.
Вы можете увидеть, как ваш веб-сайт разделен на слои в DevTools, используя панель «Слои» .
Разделение на слои
Чтобы выяснить, какие элементы должны находиться в каких слоях, основной поток проходит через дерево макета для создания дерева слоев (эта часть называется «Обновить дерево слоев» на панели производительности DevTools). Если определенные части страницы, которые должны быть отдельным слоем (например, выдвижное боковое меню), не получают его, вы можете намекнуть браузеру, используя атрибут will-change
в CSS.

У вас может возникнуть соблазн добавить слои к каждому элементу, но композиция из избыточного количества слоев может привести к более медленной работе, чем растрирование небольших частей страницы в каждом кадре, поэтому крайне важно измерить производительность рендеринга вашего приложения. Дополнительные сведения по этой теме см. в разделах «Придерживаться свойств только для композитора» и «Управление количеством слоев» .
Растр и композит вне основного потока
После того как дерево слоев создано и порядок рисования определен, основной поток передает эту информацию в поток набора текста. Затем поток наборщика растрирует каждый слой. Слой может быть большим, например, во всю длину страницы, поэтому поток наборщика делит его на фрагменты и отправляет каждый фрагмент в растровые потоки. Растровые потоки растеризуют каждый тайл и сохраняют их в памяти графического процессора.

Поток компоновщика может определять приоритеты различных растровых потоков, чтобы объекты в области просмотра (или поблизости) могли быть растрированы в первую очередь. Слой также имеет несколько фрагментов для разных разрешений, чтобы обрабатывать такие действия, как увеличение масштаба.
После растрирования тайлов поток компоновщика собирает информацию о тайлах, называемую четырехугольниками рисования, для создания кадра компоновщика .
Нарисуйте четверные | Содержит такую информацию, как расположение плитки в памяти и место на странице, где следует отрисовать плитку с учетом композиции страницы. |
Рамка композитора | Коллекция четырехугольников, представляющих собой рамку страницы. |
Затем кадр композитора передается процессу браузера через IPC. На этом этапе можно добавить еще один кадр композитора из потока пользовательского интерфейса для изменения пользовательского интерфейса браузера или из других процессов рендеринга для расширений. Эти кадры наборщика отправляются в графический процессор для отображения на экране. Если происходит событие прокрутки, поток наборщика создает еще один кадр наборщика для отправки в графический процессор.

Преимущество композитинга в том, что он выполняется без участия основного потока. Потоку композитора не нужно ждать расчета стиля или выполнения JavaScript. Вот почему компоновка только анимации считается лучшей для плавной работы. Если макет или покраску необходимо рассчитать заново, то придется задействовать основную нить.
Заворачивать
В этом посте мы рассмотрели конвейер рендеринга от анализа до композиции. Надеемся, теперь у вас есть возможность узнать больше об оптимизации производительности веб-сайта.
В следующем и последнем посте этой серии мы более подробно рассмотрим поток композитора и посмотрим, что происходит, когда вводится пользовательский ввод, например mouse move
и click
мышью.
Вам понравился пост? Если у вас есть какие-либо вопросы или предложения по поводу будущего поста, я буду рад услышать ваше мнение в разделе комментариев ниже или на @kosamari в Твиттере.
Далее: Ввод поступает в композитор
,Внутренняя работа процесса рендеринга
Это третья часть из четырех серий блогов, посвященная тому, как работают браузеры. Ранее мы рассмотрели многопроцессную архитектуру и поток навигации . В этом посте мы рассмотрим, что происходит внутри процесса рендеринга.
Процесс рендеринга затрагивает многие аспекты веб-производительности. Поскольку внутри процесса рендеринга происходит много всего, эта статья представляет собой лишь общий обзор. Если вы хотите копнуть глубже, в разделе «Производительность» раздела «Основы веб-технологий» есть гораздо больше ресурсов.
Процессы рендеринга обрабатывают веб-содержимое
Процесс рендеринга отвечает за все, что происходит внутри вкладки. В процессе рендеринга основной поток обрабатывает большую часть кода, который вы отправляете пользователю. Иногда части вашего JavaScript обрабатываются рабочими потоками, если вы используете веб-воркера или сервис-воркера. Потоки компоновщика и растра также запускаются внутри процессов рендеринга для эффективного и плавного рендеринга страницы.
Основная задача процесса рендеринга — превратить HTML, CSS и JavaScript в веб-страницу, с которой пользователь может взаимодействовать.

Разбор
Строительство ДОМ
Когда процесс рендеринга получает сообщение фиксации для навигации и начинает получать данные HTML, основной поток начинает анализировать текстовую строку (HTML) и превращать ее в объектную модель документа ( DOM ).
DOM — это внутреннее представление страницы в браузере, а также структура данных и API, с которыми веб-разработчик может взаимодействовать через JavaScript.
Синтаксический анализ HTML-документа в DOM определяется стандартом HTML . Возможно, вы заметили, что передача HTML в браузер никогда не выдает ошибку. Например, отсутствие закрывающего тега </p>
является допустимым HTML. Ошибочная разметка типа Hi! <b>I'm <i>Chrome</b>!</i>
(тег b закрывается перед тегом i) рассматривается так, как если бы вы написали Hi! <b>I'm <i>Chrome</i></b><i>!</i>
. Это связано с тем, что спецификация HTML предназначена для корректной обработки этих ошибок. Если вам интересно, как это делается, вы можете прочитать раздел « Введение в обработку ошибок и странные случаи в синтаксическом анализаторе » спецификации HTML.
Загрузка субресурса
Веб-сайт обычно использует внешние ресурсы, такие как изображения, CSS и JavaScript. Эти файлы необходимо загрузить из сети или кэша. Основной поток может запрашивать их один за другим по мере их обнаружения во время анализа для построения DOM, но для ускорения параллельно запускается «сканер предварительной загрузки». Если в документе HTML есть такие элементы, как <img>
или <link>
, сканер предварительной загрузки просматривает токены, сгенерированные анализатором HTML, и отправляет запросы в сетевой поток в процессе браузера.

JavaScript может блокировать синтаксический анализ
Когда анализатор HTML находит тег <script>
, он приостанавливает анализ HTML-документа и должен загрузить, проанализировать и выполнить код JavaScript. Почему? потому что JavaScript может изменить форму документа, используя такие вещи, как document.write()
, который меняет всю структуру DOM ( обзор модели синтаксического анализа в спецификации HTML имеет красивую диаграмму). Вот почему анализатору HTML приходится ждать запуска JavaScript, прежде чем он сможет возобновить анализ HTML-документа. Если вам интересно, что происходит при выполнении JavaScript, команда V8 проводит обсуждения и сообщения в блогах по этому поводу .
Подсказка браузеру, как вы хотите загружать ресурсы
Существует множество способов, которыми веб-разработчики могут отправлять подсказки браузеру для правильной загрузки ресурсов. Если ваш JavaScript не использует document.write()
, вы можете добавить атрибут async
или defer
в тег <script>
. Затем браузер загружает и запускает код JavaScript асинхронно и не блокирует синтаксический анализ. Вы также можете использовать модуль JavaScript, если это удобно. <link rel="preload">
- это способ сообщить браузеру, что ресурс определенно необходим для текущей навигации, и вы хотели бы загрузить как можно скорее. Вы можете прочитать больше об этом при приоритете ресурса - заставив браузер, чтобы помочь вам .
Расчет стиля
Наличие DOM недостаточно, чтобы узнать, как будет выглядеть страница, потому что мы можем стилизовать элементы страницы в CSS. Основной поток анализирует CSS и определяет вычислимый стиль для каждого узла DOM. Это информация о том, какой стиль применяется к каждому элементу на основе селекторов CSS. Вы можете увидеть эту информацию в computed
разделе DevTools.

Даже если вы не предоставляете никаких CSS, каждый узел DOM имеет вычисленный стиль. <h1>
тег отображается больше, чем тег <h2>
, а поля определяются для каждого элемента. Это потому, что в браузере есть лист стиля по умолчанию. Если вы хотите знать, на что похож CSS Chrome по умолчанию, вы можете увидеть исходный код здесь .
Макет
Теперь процесс рендеринга знает структуру документа и стилей для каждого узла, но этого недостаточно, чтобы отобразить страницу. Представьте, что вы пытаетесь описать картину своему другу по телефону. «Существует большой красный круг и маленький синий квадрат» недостаточно для вашего друга, чтобы узнать, как именно будет выглядеть картина.

Макет - это процесс для поиска геометрии элементов. Основная поток проходит через DOM и вычислимые стили и создает дерево макета, в которой есть информация, такая как координаты XY и размеры ограничивающих коробок. Дерево макета может быть аналогично дереве DOM, но оно содержит только информацию, связанную с тем, что видно на странице. Если display: none
применяется, этот элемент не является частью дерева макета (однако элемент с visibility: hidden
в дереве макета). Точно так же, если псевдоэлемент с контентом, таким как p::before{content:"Hi!"}
, Он включен в дерево макета, даже если этого нет в DOM.

Определение макета страницы является сложной задачей. Даже самый простой макет страницы, такой как блок, поток вверху вниз должен учитывать, насколько велик шрифт и где лидировать их, потому что они влияют на размер и форму абзаца; который затем влияет на то, где должен быть следующий абзац.
CSS может сделать элемент плавать в одну сторону, маскировать переполнение и изменять направления написания. Вы можете себе представить, что эта стадия макета имеет могущественную задачу. В Chrome целая команда инженеров работает над макетом. Если вы хотите увидеть подробности их работы, зарегистрировано несколько разговоров с Blinkon Conference и довольно интересно посмотреть.
Краска

Наличие DOM, стиля и макета все еще недостаточно, чтобы отобразить страницу. Допустим, вы пытаетесь воспроизвести картину. Вы знаете размер, форму и расположение элементов, но вы все равно должны судить, в каком порядке вы их рисуете.
Например, z-index
может быть установлен для определенных элементов, в этом случае живопись в порядке элементов, написанных в HTML, приведет к неправильному рендеринге.

На этом этапе краски главная нить проходит по дереву макета, чтобы создать записи краски. Запись краски - это нота процесса покраски, например «Фон сначала, затем текст, затем прямоугольник». Если вы нарисовали на элементе <canvas>
с использованием JavaScript, этот процесс может быть вам знаком.

Обновление конвейера рендеринга является дорогостоящим
Самая важная вещь, которую нужно понять в визуализации трубопровода, - это то, что на каждом этапе результат предыдущей операции используется для создания новых данных. Например, если что -то изменяется в дереве макета, то заказ краски должен быть восстановлен для затронутых частей документа.
Если вы анимируете элементы, браузер должен запускать эти операции между каждым кадром. Большинство наших дисплеев обновляют экран в 60 раз в секунду (60 кадров в секунду); Анимация будет казаться гладкой для человеческих глаз, когда вы перемещаете вещи по экрану на каждом кадре. Однако, если анимация пропускает рамки между ними, то страница появится «ярко».

Даже если ваши операции рендеринга не соответствуют обновлению экрана, эти расчеты работают в основном потоке, что означает, что его можно заблокировать, когда ваше приложение запускает JavaScript.

Вы можете разделить операцию JavaScript на небольшие куски и запланировать для работы на каждом кадре, используя requestAnimationFrame()
. Для получения дополнительной информации по этой теме см. Оптимизируйте выполнение JavaScript . Вы также можете запустить свой JavaScript в веб -работниках, чтобы не блокировать основную ветку.

Композиция
Как бы вы нарисовали страницу?
Теперь, когда браузер знает структуру документа, стиль каждого элемента, геометрию страницы и порядок краски, как он рисует страницу? Превращение этой информации в пиксели на экране называется Rasterizing.
Возможно, наивный способ справиться с этим был бы растровые детали внутри просмотра. Если пользователь прокручивает страницу, затем перемещайте растровую раму и заполните недостающие части, больше разрывы. Вот как Chrome справился с Rasterization, когда он был впервые выпущен. Тем не менее, современный браузер запускает более сложный процесс, называемый композитингом.
Что такое композиция
Compositing - это метод для разделения частей страницы на слои, расчистить их отдельно и композит в виде страницы в отдельном потоке, называемом потоком композитора. Если происходит свиток, поскольку слои уже растилизованы, все, что ему нужно сделать, это составить новую раму. Анимация может быть достигнута таким же образом путем перемещения слоев и сочинения новой кадры.
Вы можете увидеть, как ваш сайт разделен на слои в Devtools, используя панель слоев .
Разделение на слои
Чтобы выяснить, какие элементы должны быть в каких слоях, основная нить проходит через дерево макета, чтобы создать дерево слоев (эта часть называется «дерево слоев обновлений» на панели производительности DevTools). Если определенные части страницы, которые должны быть отдельным слоем (например, Slide-In Side Menu), не получают их, то вы можете намекнуть на браузер, используя атрибут will-change
в CSS.

У вас может возникнуть соблазн дать слои каждому элементу, но композиция по избыточному количеству слоев может привести к более медленной работе, чем растилизация небольших частей страницы каждого кадра, поэтому крайне важно, чтобы вы измеряли производительность вашего приложения. Для получения дополнительной информации о теме см. В Plake to Compositor-Properties и управляйте количеством слоев .
Растровый и композитный от основной резьбы
Как только дерево слоя создается и определяется заказа покраски, основной поток передает эту информацию в поток композитора. Поток композитора затем нарывает каждый слой. Слой может быть большим, как вся длина страницы, поэтому нить композитора делит их на плитку и отправляет каждую плитку в растровые потоки. Растровые нити растилируют каждую плитку и храните их в памяти графического процессора.

Поток композитора может расставить приоритеты в различных растровых потоках, так что вещи в рамках просмотра (или поблизости) можно сначала быть растровым. У слоя также есть несколько уточнений для различных решений, чтобы справиться с такими вещами, как увеличение действия.
Как только плитки будут ракурсированы, нить композитора собирает информацию о плитках, называемой нарисованными квадратами для создания кадра композитора .
Нарисуйте квадраты | Содержит информацию, такую как местоположение плитки в памяти и где на странице, чтобы нарисовать плитку с учетом композиции страницы. |
Кадра композитора | Коллекция розыгрыша, которые представляют кадр страницы. |
Затем в процесс браузера отправляется кадр композитора через IPC. На этом этапе можно добавить другую кадр композитора из потока пользовательского интерфейса для изменения пользовательского интерфейса браузера или из других процессов рендеринга для расширений. Эти кадры композитора отправляются в GPU, чтобы отобразить его на экране. Если появляется событие прокрутки, поток композитора создает еще одну кадр композитора, которая будет отправлена в графический процессор.

Преимущество композиции заключается в том, что это делается без участия в основном потоке. Поток композитора не должен ждать расчета стиля или выполнения JavaScript. Вот почему только композиция анимации считаются лучшими для плавного производительности. Если макет или краска должны быть снова рассчитаны, то основной поток должен быть вовлечен.
Заворачивать
В этом посте мы посмотрели на рендеринг трубопровода от разбора в композитинг. Надеемся, что теперь вы уполномочены узнать больше о оптимизации производительности веб -сайта.
В следующем и последнем посте этой серии мы рассмотрим поток композитора более подробно и посмотрим, что происходит, когда ввод пользователя, такого как mouse move
и click
.
Вам понравился пост? Если у вас есть какие -либо вопросы или предложения для будущего поста, я бы хотел услышать от вас в разделе комментариев ниже или @kosamari в Твиттере.
Далее: ввод идет к композитору
,Внутренняя работа процесса рендеринга
Это часть 3 из 4 -й серии блогов, рассматривая, как работают браузеры. Ранее мы освещали многопроцессорную архитектуру и навигацию . В этом посте мы рассмотрим, что происходит внутри процесса рендеринга.
Процесс рендеринга затрагивает многие аспекты веб -производительности. Поскольку внутри процесса рендеринга происходит много всего, этот пост является лишь общим обзором. Если вы хотите копать глубже, в разделе производительности веб -основных основных ресурсов.
Процессы рендеринга обрабатывают веб -содержание
Процесс рендеринга отвечает за все, что происходит внутри вкладки. В процессе рендеринга основной поток обрабатывает большую часть кода, который вы отправляете пользователю. Иногда части вашего JavaScript обрабатываются рабочими потоками, если вы используете веб -работника или обслуживающего работника. Композитор и растровые потоки также запускаются внутри процессов рендеринга, чтобы эффективно и плавно отображать страницу.
Основная задача процесса рендеринга - превратить HTML, CSS и JavaScript в веб -страницу, с которой пользователь может взаимодействовать.

Диапазон
Строительство DOM
Когда процесс рендеринга получает сообщение о коммите для навигации и начинает получать данные HTML, основной поток начинает анализировать текстовую строку (HTML) и превращать их в D -Ocument O Bject M Odel ( DOM ).
DOM - это внутреннее представление браузера на странице, а также структура данных и API, с которыми веб -разработчик может взаимодействовать через JavaScript.
Расположение документа HTML в DOM определяется стандартом HTML . Возможно, вы заметили, что подача HTML в браузер никогда не бросает ошибку. Например, отсутствующее закрытие </p>
тег является действительным HTML. Ошибочная разметка, как Hi! <b>I'm <i>Chrome</b>!</i>
Hi! <b>I'm <i>Chrome</i></b><i>!</i>
. Это связано с тем, что спецификация HTML предназначена для изящного обращения с этими ошибками. Если вам любопытно, как эти вещи сделаны, вы можете прочитать « Введение в обработку ошибок и странные случаи в разделе синхронизатора » в разделе HTML Spec.
Загрузка Subresource
Веб -сайт обычно использует внешние ресурсы, такие как изображения, CSS и JavaScript. Эти файлы должны быть загружены из сети или кэша. Основной поток может запросить их один за другим, поскольку они находят их, а также анализ, чтобы построить DOM, но чтобы ускорить, «сканер предварительного нагрузки» работает одновременно. Если в документе HTML есть такие вещи, как <img>
или <link>
, сканер предварительного нагрузки заглядывает на токены, сгенерированные HTML -анализатором, и отправляет запросы в сетевой поток в процессе браузера.

JavaScript может заблокировать анализ
Когда анализатор HTML находит тег <script>
, он останавливает анализ документа HTML и должен загружать, разрабатывать и выполнять код JavaScript. Почему? Поскольку JavaScript может изменить форму документа, используя такие вещи, как document.write()
, который изменяет всю структуру DOM ( обзор модели анализа в спецификации HTML имеет хорошую диаграмму). Вот почему анализатор HTML должен ждать, пока JavaScript запустит, прежде чем он сможет возобновить анализ документа HTML. Если вам интересно, что происходит в исполнении JavaScript, у команды V8 есть переговоры и сообщения в блоге по этому поводу .
Намекните на браузер, как вы хотите загрузить ресурсы
Есть много способов, которыми веб -разработчики могут отправлять подсказки в браузер, чтобы хорошо загружать ресурсы. Если ваш JavaScript не использует document.write()
, вы можете добавить атрибут async
или defer
в тег <script>
. Затем браузер загружает и запускает код JavaScript асинхронно и не блокирует анализ. Вы также можете использовать модуль JavaScript, если это подходит. <link rel="preload">
- это способ сообщить браузеру, что ресурс определенно необходим для текущей навигации, и вы хотели бы загрузить как можно скорее. Вы можете прочитать больше об этом при приоритете ресурса - заставив браузер, чтобы помочь вам .
Расчет стиля
Наличие DOM недостаточно, чтобы узнать, как будет выглядеть страница, потому что мы можем стилизовать элементы страницы в CSS. Основной поток анализирует CSS и определяет вычислимый стиль для каждого узла DOM. Это информация о том, какой стиль применяется к каждому элементу на основе селекторов CSS. Вы можете увидеть эту информацию в computed
разделе DevTools.

Даже если вы не предоставляете никаких CSS, каждый узел DOM имеет вычисленный стиль. <h1>
тег отображается больше, чем тег <h2>
, а поля определяются для каждого элемента. Это потому, что в браузере есть лист стиля по умолчанию. Если вы хотите знать, на что похож CSS Chrome по умолчанию, вы можете увидеть исходный код здесь .
Макет
Теперь процесс рендеринга знает структуру документа и стилей для каждого узла, но этого недостаточно, чтобы отобразить страницу. Представьте, что вы пытаетесь описать картину своему другу по телефону. «Существует большой красный круг и маленький синий квадрат» недостаточно для вашего друга, чтобы узнать, как именно будет выглядеть картина.

Макет - это процесс для поиска геометрии элементов. Основная поток проходит через DOM и вычислимые стили и создает дерево макета, в которой есть информация, такая как координаты XY и размеры ограничивающих коробок. Дерево макета может быть аналогично дереве DOM, но оно содержит только информацию, связанную с тем, что видно на странице. Если display: none
применяется, этот элемент не является частью дерева макета (однако элемент с visibility: hidden
в дереве макета). Точно так же, если псевдоэлемент с контентом, таким как p::before{content:"Hi!"}
, Он включен в дерево макета, даже если этого нет в DOM.

Определение макета страницы является сложной задачей. Даже самый простой макет страницы, такой как блок, поток вверху вниз должен учитывать, насколько велик шрифт и где лидировать их, потому что они влияют на размер и форму абзаца; который затем влияет на то, где должен быть следующий абзац.
CSS может сделать элемент плавать в одну сторону, маскировать переполнение и изменять направления написания. Вы можете себе представить, что эта стадия макета имеет могущественную задачу. В Chrome целая команда инженеров работает над макетом. Если вы хотите увидеть подробности их работы, зарегистрировано несколько разговоров с Blinkon Conference и довольно интересно посмотреть.
Краска

Наличие DOM, стиля и макета все еще недостаточно, чтобы отобразить страницу. Допустим, вы пытаетесь воспроизвести картину. Вы знаете размер, форму и расположение элементов, но вы все равно должны судить, в каком порядке вы их рисуете.
Например, z-index
может быть установлен для определенных элементов, в этом случае живопись в порядке элементов, написанных в HTML, приведет к неправильному рендеринге.

На этом этапе краски главная нить проходит по дереву макета, чтобы создать записи краски. Запись краски - это нота процесса покраски, например «Фон сначала, затем текст, затем прямоугольник». Если вы нарисовали на элементе <canvas>
с использованием JavaScript, этот процесс может быть вам знаком.

Обновление конвейера рендеринга является дорогостоящим
Самая важная вещь, которую нужно понять в визуализации трубопровода, - это то, что на каждом этапе результат предыдущей операции используется для создания новых данных. Например, если что -то изменяется в дереве макета, то заказ краски должен быть восстановлен для затронутых частей документа.
Если вы анимируете элементы, браузер должен запускать эти операции между каждым кадром. Большинство наших дисплеев обновляют экран в 60 раз в секунду (60 кадров в секунду); Анимация будет казаться гладкой для человеческих глаз, когда вы перемещаете вещи по экрану на каждом кадре. Однако, если анимация пропускает рамки между ними, то страница появится «ярко».

Даже если ваши операции рендеринга не соответствуют обновлению экрана, эти расчеты работают в основном потоке, что означает, что его можно заблокировать, когда ваше приложение запускает JavaScript.

Вы можете разделить операцию JavaScript на небольшие куски и запланировать для работы на каждом кадре, используя requestAnimationFrame()
. Для получения дополнительной информации по этой теме см. Оптимизируйте выполнение JavaScript . Вы также можете запустить свой JavaScript в веб -работниках, чтобы не блокировать основную ветку.

Композиция
Как бы вы нарисовали страницу?
Теперь, когда браузер знает структуру документа, стиль каждого элемента, геометрию страницы и порядок краски, как он рисует страницу? Превращение этой информации в пиксели на экране называется Rasterizing.
Возможно, наивный способ справиться с этим был бы растровые детали внутри просмотра. Если пользователь прокручивает страницу, затем перемещайте растровую раму и заполните недостающие части, больше разрывы. Вот как Chrome справился с Rasterization, когда он был впервые выпущен. Тем не менее, современный браузер запускает более сложный процесс, называемый композитингом.
Что такое композиция
Compositing - это метод для разделения частей страницы на слои, расчистить их отдельно и композит в виде страницы в отдельном потоке, называемом потоком композитора. Если происходит свиток, поскольку слои уже растилизованы, все, что ему нужно сделать, это составить новую раму. Анимация может быть достигнута таким же образом путем перемещения слоев и сочинения новой кадры.
Вы можете увидеть, как ваш сайт разделен на слои в Devtools, используя панель слоев .
Разделение на слои
Чтобы выяснить, какие элементы должны быть в каких слоях, основная нить проходит через дерево макета, чтобы создать дерево слоев (эта часть называется «дерево слоев обновлений» на панели производительности DevTools). Если определенные части страницы, которые должны быть отдельным слоем (например, Slide-In Side Menu), не получают их, то вы можете намекнуть на браузер, используя атрибут will-change
в CSS.

У вас может возникнуть соблазн дать слои каждому элементу, но композиция по избыточному количеству слоев может привести к более медленной работе, чем растилизация небольших частей страницы каждого кадра, поэтому крайне важно, чтобы вы измеряли производительность вашего приложения. Для получения дополнительной информации о теме см. В Plake to Compositor-Properties и управляйте количеством слоев .
Растровый и композитный от основной резьбы
Как только дерево слоя создается и определяется заказа покраски, основной поток передает эту информацию в поток композитора. Поток композитора затем нарывает каждый слой. Слой может быть большим, как вся длина страницы, поэтому нить композитора делит их на плитку и отправляет каждую плитку в растровые потоки. Растровые нити растилируют каждую плитку и храните их в памяти графического процессора.

Поток композитора может расставить приоритеты в различных растровых потоках, так что вещи в рамках просмотра (или поблизости) можно сначала быть растровым. У слоя также есть несколько уточнений для различных решений, чтобы справиться с такими вещами, как увеличение действия.
Как только плитки будут ракурсированы, нить композитора собирает информацию о плитках, называемой нарисованными квадратами для создания кадра композитора .
Нарисуйте квадраты | Содержит информацию, такую как местоположение плитки в памяти и где на странице, чтобы нарисовать плитку с учетом композиции страницы. |
Кадра композитора | Коллекция розыгрыша, которые представляют кадр страницы. |
Затем в процесс браузера отправляется кадр композитора через IPC. На этом этапе можно добавить другую кадр композитора из потока пользовательского интерфейса для изменения пользовательского интерфейса браузера или из других процессов рендеринга для расширений. Эти кадры композитора отправляются в GPU, чтобы отобразить его на экране. Если появляется событие прокрутки, поток композитора создает еще одну кадр композитора, которая будет отправлена в графический процессор.

Преимущество композиции заключается в том, что это делается без участия в основном потоке. Поток композитора не должен ждать расчета стиля или выполнения JavaScript. Вот почему только композиция анимации считаются лучшими для плавного производительности. Если макет или краска должны быть снова рассчитаны, то основной поток должен быть вовлечен.
Заворачивать
В этом посте мы посмотрели на рендеринг трубопровода от разбора в композитинг. Надеемся, что теперь вы уполномочены узнать больше о оптимизации производительности веб -сайта.
В следующем и последнем посте этой серии мы рассмотрим поток композитора более подробно и посмотрим, что происходит, когда ввод пользователя, такого как mouse move
и click
.
Вам понравился пост? Если у вас есть какие -либо вопросы или предложения для будущего поста, я бы хотел услышать от вас в разделе комментариев ниже или @kosamari в Твиттере.