Как браузер парсит html
Перейти к содержимому

Как браузер парсит html

  • автор:

Критические этапы рендеринга

Критические этапы рендеринга (Critical Rendering Path) — это последовательность шагов, которые выполняет браузер, когда преобразуется HTML, CSS и JavaScript в пиксели, которые вы видите на экране. Оптимизация этих шагов улучшает производительность рендера. Эти этапы включают в себя работу с Document Object Model(DOM), CSS Object Model(CSSOM), деревом рендера (render tree) и компоновкой объектов (layout)

Объектная модель документа DOM создаётся в тот момент, когда браузер парсит HTML. Этот HTML может запрашивать JavaScript, который может модифицировать DOM. HTML может запросить стили, которые участвуют в создании CSS Object Model. Движок браузера комбинирует эти две объектные модели, чтобы создать дерево рендера (render tree). Компоновка (layout) определяет размеры и позицию каждого элемента на странице. Как только компоновка определена — пиксели отрисовываются на экране.

Оптимизация критических этапов рендеринга улучшает время до первого рендера. Понимание и оптимизация этих этапов чрезвычайно важны для того, чтобы рендерить приложение с нужной частотой кадров (60 кадров в секунду, fps) и предоставить пользователю удобный, плавный интерфейс.

Понимание этапов (CRP)

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

Загрузка веб-страницы или приложения начинается с запроса HTML. Сервер возвращает HTTP-ответ, состоящий из заголовков (headers) и тела запроса. Именно в теле запроса содержится HTML-документ. Браузер начинает парсить загружаемый HTML, преобразуя полученные байты документа в DOM-дерево. Браузер создаёт новый запрос каждый раз, когда он находит ссылки на внешние ресурсы, будь то файлы стилей, скриптов или ссылки на изображения. Некоторые запросы являются блокирующими. Это означает, что пока такие запросы выполняются — другие запросы приостанавливаются. Браузер продолжает парсить HTML и создавать DOM до тех пор, пока запрос на получение HTML не подходит к концу. После завершения парсинга DOM, браузер конструирует CSS модель. Как только эти модели сформированы, браузер строит дерево рендера (render tree), в котором вычисляет стили для каждого видимого элемента страницы. После формирования дерева происходит компоновка (layout), которая определяет положение и размеры элементов этого дерева. Как только этап завершён — страница рендерится. Или «отрисовывается» (paint) на экране.

Document Object Model

Построение DOM инкрементально. Ответ в виде HTML превращается в токены, которые превращаются в узлы (nodes), которые формируют DOM дерево. Простейший узел начинается с startTag-токена и заканчивается токеном endTag. Узлы содержат всю необходимую информацию об HTML-элементе, соответствующем этому узлу. Узлы (nodes) связаны с Render Tree с помощью иерархии токенов: если какой-то набор startTag и endTag-токенов появляется между уже существующим набором токенов, мы получаем узел (node) внутри узла (node), то есть получаем иерархию дерева DOM.

Чем больше количество узлов (node) имеет приложение, тем дольше происходит формирование DOM tree, а значит дольше происходит обработка критических этапов рендеринга. Измеряйте! Несколько лишних узлов (node) не сделают погоды, но divitis обязательно приведёт к подвисаниям.

CSS Object Model

DOM несёт в себе всё содержимое страницы. CSSOM содержит все стили страницы, то есть данные о том, как стилизовать DOM. CSSOM похож на DOM, но всё же отличается. Если формирование DOM инкрементально, CSSOM — нет. CSS блокирует рендер: браузер блокирует рендеринг страницы до тех пор, пока не получит и не обработает все CSS-правила. CSS блокирует рендеринг, потому что правила могут быть перезаписаны, а значит, необходимо дождаться построения CSSOM, чтобы убедиться в отсутствии дополнительных переопределений.

У CSS имеются свои правила валидации токенов. Помните, что C в CSS означает «Cascade». CSS-правила ниспадают каскадом. Иными словами, когда парсер преобразует токены в узлы (nodes), вложенные узлы наследуют стили от родительских. Инкрементальная обработка недоступна для CSS, потому что набор следующих правил может перезаписать предыдущие. Объектная модель CSS (CSSOM) строится по мере парсинга CSS, но она не может быть использована для построения дерева рендера (render tree), потому что может оказаться так, что следующий набор правил может сделать какой-либо из узлов дерева невидимым на экране. Это может привести к лишнему вызову компоновки и перерасчёта стилей.

Говоря о производительности селекторов (selector), наименее специфичные селекторы срабатывают быстрее. Например, .foo <> сработает быстрее .bar .foo <> . В первом случае, условно, понадобится одна операция, чтобы найти элемент .foo , во втором случае, сначала будут найдены все .foo , а потом браузер пройдёт вверх по дереву в поисках родительского элемента .bar . Более специфичные селекторы требуют от браузера большего количества работы, но эти проблемы, вероятно, не стоят их оптимизации.

Если вы измерите время, требуемое на парсинг CSS, вы будете удивлены тем, как быстро работают браузеры. Более специфичные правила более затратны, потому что требуют обхода большего числа узлов в DOM дереве, но эта дороговизна обходится довольно дёшево, особенно в сравнении с другими узкими местами производительности. Сначала измеряйте. Потом оптимизируйте, если это действительно необходимо. Вероятно, специфичность селекторов не то, что действительно затормаживает ваше приложение. Когда дело доходит до оптимизации CSS, улучшение производительность селекторов ускоряет рендеринг лишь на микросекунды. Существуют другие пути оптимизации CSS (en-US) , такие как унификация, разделение CSS-файлов на разные файлы на основе медиавыражений.

Дерево рендера (Render Tree)

Дерево рендера охватывает сразу и содержимое страницы, и стили: это место, где DOM и CSSOM деревья комбинируются в одно дерево. Для построения дерева рендера браузер проверяет каждый узел (node) DOM, начиная от корневого (root) и определяет, какие CSS-правила нужно присоединить к этому узлу.

Дерево рендера охватывает только видимое содержимое. Например, секция head (в основном) не содержит никакой видимой информации, а потому может не включаться в дерево. Кроме того, если у какого-то узла стоит свойство display: none , оно так же не включается в дерево (как и потомки этого узла).

Компоновка (Layout)

В тот момент, когда дерево рендера (render tree) построено, становится возможным этап компоновки (layout). Компоновка зависит от размеров экрана. Этот этап определяет, где и как на странице будут спозиционированы элементы и каковы связи между элементами.

Что насчёт ширины элемента? Блочные элементы по определению имеют ширину в 100% от ширины их родителя. Элемент с шириной в 50% будет иметь ширину в два раза меньше родительской. Если не указано иного, элемент body имеет ширину 100%, то есть 100% ширины родителя — видимой области viewport (окна документа).

Мета тэг viewport, который вы можете указать в Head страницы, определяет ширину видимой области и влияет на компоновку. Без этого тэга браузеры используют ширину «по умолчанию», которая обычно составляет 960px. В браузерах, открывающихся по умолчанию в полноэкранном режиме, например, в браузере телефона, установка тега установит ширину видимой области в 100% от ширины экрана устройства, вместо того, чтобы использовать ширину по умолчанию. Эта ширина ( device-width) изменяется каждый раз, когда пользователь поворачивает телефон. Это приводит к запуску этапа компоновки. Равно как и при изменении размеров окна в обычном браузере.

На производительность компоновки (layout) непосредственно влияет DOM — чем больше узлов (nodes) в вашем документе, тем больше времени понадобится на перерасчёт позиций и размеров всех элементов. Компоновка может стать узким местом, ведущим к зависаниям, особенно если выполняется одновременно со скроллом или другой анимацией. И хотя задержка 20мс при загрузке или переориентации экрана может быть приемлемой, это всё равно может привести к подвисаниям при анимации и скролле. Каждый раз, когда дерево рендера (render tree) модифицируется, например, из-за добавления узла (node), его модификации или при изменении стилей box-модели, запускается компоновка.

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

Отрисовка (Paint)

Последний этап в нашем списке — отрисовка (paint) пикселей на экране. Когда дерево рендера (render tree) создано, компоновка (layout) произошла, пиксели могут быть отрисованы. При первичной загрузке документа (onload) весь экран будет отрисован. После этого будут перерисовываться только необходимые к обновлению части экрана, так как браузер старается оптимизировать процесс отрисовки, избегая ненужной работы. Так, если у вас в документе есть два элемента, перерисовываться будет только тот, который вы изменили. Время отрисовки зависит от того, какой тип обновления применился к дереву рендера (render tree). И хотя отрисовка — это очень быстрый процесс, и он, вероятно, слабо влияет на производительность, очень важно помнить, что оба этапа — компоновка (layout) и отрисовка (paint) должны работать сообща и укладываться в частоту обновления кадров. Каждое CSS-свойство, применяемое к любому узлу (node) увеличивает время отрисовки, но полное удаление стиля, способное сэкономить вам 0.001мс, вряд ли даст вам желаемый результат, но зато с лёгкостью ухудшит пользовательский опыт. Помните — сначала нужно измерять, а потом оптимизировать только необходимое!

Оптимизация CRP

Улучшайте загрузку страницы с помощью приоритизации ресурсов, с помощью контролирования порядка, в котором они грузятся и с помощью уменьшения размеров файлов. Главные подсказки здесь:

  1. Уменьшайте количество критических ресурсов, откладывая их загрузку, помечая их как async и/или группируя их;
  2. Оптимизируйте количество необходимых запросов, а так же размеры файлов;
  3. Оптимизируйте порядок так, чтобы критические ресурсы загружались в первую очередь, сокращая таким образом длину критических этапов рендеринга.

Found a content problem with this page?

  • Edit the page on GitHub.
  • Report the content issue.
  • View the source on GitHub.

This page was last modified on 3 авг. 2023 г. by MDN contributors.

Как браузер рендерит страницу?

Как только страница загрузилась, браузер преобразует полученную от сервера строку с HTML в DOM-дерево (парсинг).

Когда парсер встречает ссылки, он создает запросы для их скачивания. Процесс парсинга HTML заканчивается когда все ресурсы скачаны, а сборка DOM-дерева завершена.

Далее браузер преобразует CSS в CSS-дерево.

Когда оба дерева созданы, браузер комбинирует их в одно — Render-дерево, в нем вычисляются стили для каждого видимого элемента страницы.

Далее браузер занимается компоновкой, определяя размеры и позицию элементов в Render-дереве.

Как только компоновка завершена — страница отрисовывается на экране.

Глубокое понимание

Общее понимание можно конкретизировать и разделить на CRP этапы (critical rendering path) или этапы критические рендеринга:

  • Построение DOM-дерева
  • Построение CSSOM-дерева
  • Создание Render-дерева
  • Компоновка
  • Отрисовка

Построение DOM-дерева (Document Object Model)

Работать напрямую с HTML-разметкой довольно дорого и долго.

Поэтому сначала браузер парсит HTML, а затем создает его абстрактное представление — объектную модель документа (DOM).

Построение DOM является инкрементальным, то есть парсер последовательно преобразует весь HTML-документ в токены, из которых формирует узлы.

Токен (token)

  • Начинается со startTag , заканчивается endTag

Узел (node)

  • Содержит информацию о HTML-элементе и своих потомках
  • Состоит из токенов с определенной иерархией

Чем больше количество узлов, тем дольше происходит формирование DOM.

Внешние ресурсы

Когда парсер находит теги с ссылками на внешние ресурсы, он запрашивает их скачивание. Такие запросы могут блокировать построение DOM, например:

  • Блокируют
    • Скрипты
    • Стили
    • Изображения
    • Шрифты

    Параллельно созданию DOM-дерева происходит создание CSSOM-дерева.

    Построение CSSOM-дерева (CSS Object Model)

    CSSOM-дерево содержит все данные о стилях DOM-дерева.

    Преобразование CSS в CSSOM проходит так, чтобы вложенные узлы наследовали стили от родительских.

    Процесс построения CSSOM не инкрементальный, то есть он блокирует процесс построения CSSOM-дерева до момента когда все CSS-правила будут получены и обработаны.

    Это связано возможностью перезаписать CSS-правило из любого места CSS-документа.

    Производительность селекторов

    Наименее специфичные селекторы срабатывают быстрее, например:

    .foo <> /* сработает быстрее */

    Для поиска .foo понадобится одна операция.

    .bar .foo <>

    Сначала будут найдены все .foo , а потом браузер пройдёт вверх по дереву в поисках родительского элемента .bar

    Более специфичные селекторы требуют от браузера большего количества работы, но эти проблемы не стоят их оптимизации.

    Создание Render-дерева (Render Tree)

    Как только браузер составил DOM и CSSOM, он объединяет их в общее дерево рендеринга — Render-дерево.

    Процесс объединения запускает проверку каждого DOM-узла, начиная от корневого, затем совмещает каждый элемент с его стилями из CSSOM.

    display: none

    Наличие свойства display: none предполагает исключение узла и его потомков из процесса создания Render-дерева.

    Когда Render-дерево построено запускается процесс компоновки.

    Компоновка (Layout)

    Компоновка определяет позиции, размеры и как одни элементы страницы влияют на расположение других.

    Компоновка делится на два этапа:

    Глобальная компоновка

    Просчитывает каждый элемент в дереве и является очень дорогой операцией, например:

    • Изменение viewport

    Инкрементальная компоновка

    Просчитывает частично только «грязные» элементы, которые появляются в случае:

    • Изменения стилей box-модели элемента
    • Добавления нового узла или элемента

    О viewport

    viewport определяет ширину видимой области экрана, которая по умолчанию ровна 960px.

    Установка width=device-width делает ширину видимой области в 100% от ширины экрана устройства.

    device-width изменяется каждый раз, когда пользователь поворачивает телефон. Это приводит к запуску этапа компоновки, как и при изменении размеров окна в обычном браузере.

    Производительность

    На производительность компоновки влияет DOM — чем больше узлов, тем больше времени понадобится на перерасчёт позиций и размеров всех элементов.

    Вызов компоновки во время скролла или анимации, может стать узким местом

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

    Отрисовка (Paint)

    Когда Render-дерево создано, а компоновка произведена — браузер начинает рисовать страницу, располагая пиксели в нужные места экрана, чтобы все элементы страницы отобразились там где должны.

    Отрисовка делится на два этапа:

    Глобальная отрисовка

    Первичная полная отрисовка всей страницы.

    Инкрементальная отрисовка

    Браузер делит весь viewport на прямоугольные участки. Если изменения ограничены одним участком, то он обозначается «грязным», а это приводит к его перерисовкe.

    Порядок отрисовки связан со стековым контекстом. В общих чертах, отрисовка начинается с заднего плана и постепенно переходит к переднему.

    background-color background-image border children outline

    Отрисовка является самым дорогим процессом.

    Влияние на производительность отрисовки

    • Создание запроса к статическому ресурсу из HTML
    • Скорость получения ответа от сервера
    • Загрузка статического ресурса
    • Парсинг и выполнение скриптов

    Для гладкой работы интерфейса процесс отрисовки должен укладываться в стандартную частоту кадров экрана — 60 fps или 16ms.

    Дополнительно

    Композитинг

    Компоновка и отрисовка работают за счёт CPU, поэтому относительно медленные, это делает плавные анимации невероятно дорогими.

    Для плавных анимаций в браузерах предусмотрен — композитинг.

    Композитинг это разделение содержимого страницы на «слои», которые браузер будет перерисовывать. Эти слои друг от друга не зависят, поэтому изменение элемента в одном слое не затрагивает элементы из других слоёв, и перерисовывать их становится не нужно.

    Применение таких свойств, как transform , выносит элемент на отдельный композитный слой.

    Перерисовка (reflow, repaint)

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

    С помощью requestAnimationFrame мы можем указать браузеру что хотим запускать анимацию в один цикл обновления — animation frame .

    Оптимизация CRP

    • Уменьшайте количество критических ресурсов, откладывая их загрузку, помечая их как async и/или группируя их
    • Оптимизируйте количество необходимых запросов, а так же размеры файлов
    • Оптимизируйте порядок так, чтобы критические ресурсы загружались в первую очередь, сокращая таким образом длину критических этапов рендеринга.

    Полезное:

    • https://developer.mozilla.org/ru/docs/Web/Performance/Critical_rendering_path
    • https://doka.guide/tools/how-the-browser-creates-pages
    • https://www.youtube.com/watch?v=InDkFI_LwGM

    Как браузер рисует страницы

    Как обрабатывается HTML, CSS и JS код перед тем, как станет веб-страницей.

    Время чтения: 9 мин

    Открыть/закрыть навигацию по статье

    1. Кратко
    2. Получение ресурсов, Fetching
    3. Парсинг, Parsing
      1. DOM
      1. Render Tree
      1. Глобальный и инкрементальный Layout
      2. «Грязные» элементы
      1. Порядок отрисовки
      1. Саша Беспоясов советует
      1. Что такое прогрессивный рендеринг (progressive rendering)?

      Обновлено 8 марта 2023

      Кратко

      Скопировать ссылку «Кратко» Скопировано

      Чтобы нарисовать на экране результат работы нашего кода, браузеру нужно выполнить несколько этапов:

      1. Сперва ему нужно скачать исходники.
      2. Затем их нужно прочитать и распарсить.
      3. После этого браузер приступает к рендерингу — отрисовке.

      Каждый из процессов очень сложен, и мы не будем рассматривать их до мельчайших подробностей.

      Мы лишь обратим внимание на те детали, которые необходимо знать фронтенд-разработчикам, чтобы лучше понимать, почему разные решения по-разному влияют на производительность и скорость отрисовки.

      Начнём по порядку.

      Получение ресурсов, Fetching

      Скопировать ссылку «Получение ресурсов, Fetching» Скопировано

      Ресурсы браузер получает с помощью запросов к серверу. В ответ он может получить как, например, данные в виде JSON, так и картинки, видео, файлы стилей и скриптов.

      Самый первый запрос к серверу — обычно запрос на получение HTML-страницы (чаще всего index . html ).

      В её коде содержатся ссылки на другие ресурсы, которые браузер тоже запросит у сервера:

            Document   Привет!    DOCTYPE html> html lang="en"> head> link href="/style.css" rel="stylesheet"> title>Documenttitle> head> body> img src="/hello.jpg" alt="Привет!"> script src="/index.js"> script> body> html>      

      В примере выше браузер запросит также:

      • файл стилей style . css ;
      • изображение hello . jpg ;
      • и скрипт index . js .

      Парсинг, Parsing

      Скопировать ссылку «Парсинг, Parsing» Скопировано

      По мере того как скачивается HTML-страница, браузер пытается её «прочитать» — распарсить.

      DOM

      Скопировать ссылку «DOM» Скопировано

      Браузер работает не с текстом разметки, а с абстракциями над ним. Одна из таких абстракций, результат парсинга HTML-кода, называется DOM.

      DOM (Document Object Model) — абстрактное представление HTML-документа, с помощью которого браузер может получать доступ к его элементам, изменять его структуру и оформление.

      DOM — это дерево. Корень этого дерева — это элемент HTML, все остальные элементы — это дочерние узлы.

      Для такого документа:

           Hello   

      Hello world

      Привет!
      html> head> meta charset="utf-8"> title>Hellotitle> head> body> p class="text">Hello worldp> img src="/hello.jpg" alt="Привет!"> body> html>

      . получится такое дерево:

      DOM дерево

      Пока браузер парсит документ и строит DOM, он натыкается на элементы типа , , , которые содержат ссылки на другие ресурсы.

      Если ресурс неблокирующий (например, изображение), браузер запрашивает его параллельно с парсингом оставшейся части документа. Блокирующие ресурсы (например, скрипты) приостанавливают обработку до своей полной загрузки.

      Мы можем указывать браузеру, как именно ему следует запрашивать некоторые ресурсы, например, скрипты. Это может быть полезно, когда в скрипте мы собираемся работать с элементами, которые находятся в разметке после тега :

       // script.jsconst image = document.getElementById('image') // script.js const image = document.getElementById('image')      
         Hello world  body> script src="script.js"> script> img src="/hello.jpg" alt="Hello world" id="image"> body>      

      В этом случае image = = = undefined , потому что браузер успел распарсить только часть документа до этого тега .

      А в этом всё в порядке, изображение найдётся:

         Hello world  body> img src="/hello.jpg" alt="Hello world" id="image"> script src="script.js"> script> body>      

      И в этом тоже порядок, атрибут defer скажет браузеру продолжать парсить страницу и выполнить скрипт потом:

         Hello world  body> script src="script.js" defer> script> img src="/hello.jpg" alt="Hello world" id="image"> body>      

      CSSOM

      Скопировать ссылку «CSSOM» Скопировано

      Когда браузер находит элемент , который указывает на файл стилей, браузер скачивает и парсит его. Результат парсинга CSS-кода — CSSOM.

      CSSOM (CSS Object Model) — по аналогии с DOM, представление стилевых правил в виде дерева.

      Для документа выше с такими стилями:

       body  font-size: 1.5rem;> .text  color: red;> img  max-width: 100%;> body  font-size: 1.5rem; > .text  color: red; > img  max-width: 100%; >      

      . получим такое дерево:

      CSSOM дерево

      Чтение стилей приостанавливает чтение кода страницы. Поэтому рекомендуется в самом начале отдавать только критичные стили — которые есть на всех страницах и конкретно на этой. Так мы уменьшаем время ожидания, пока «страница загрузится».

      Благодаря оптимизациям (например, сканеру предзагрузки) стили могут не блокировать чтение HTML, но они точно блокируют выполнение JavaScript, потому что в JS могут использоваться CSS-селекторы для выборки элементов.

      Render Tree

      Скопировать ссылку «Render Tree» Скопировано

      После того как браузер составил DOM и CSSOM, он объединяет их в общее дерево рендеринга — Render Tree.

      Render Tree — это термин, который используется движком WebKit, в других движках он может отличаться. Например, Gecko использует термин Frame Tree.

      В итоге для нашего документа выше мы получим такое дерево:

      Render tree

      Обратите внимание, что в Render tree попадают только видимые элементы. Если бы у нас был элемент, спрятанный через display : none , он бы в это дерево не попал. Об этом подробнее мы ещё поговорим дальше.

      Общая схема парсинга выглядит вот так:

      Общая схема парсинга HTML и CSS

      На первых шагах мы разбираемся с HTML и CSS, а затем объединяем их в Render Tree.

      Вычисление позиции и размеров, Layout

      Скопировать ссылку «Вычисление позиции и размеров, Layout» Скопировано

      После того как у браузера появилось дерево рендеринга (Render Tree), он начинает «расставлять» элементы на странице. Этот процесс называется Layout.

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

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

      Важно помнить, что Layout построен на поточной модели компоновки. Это значит, что если элементы не влияют на расположение и размеры других элементов, то их положение и размеры можно просчитать за один подход.

      Именно поэтому при вёрстке макетов рекомендуется «находиться в потоке» — чтобы браузеру не приходилось несколько раз пересчитывать один и тот же элемент, так страница отрисовывается быстрее.

      Глобальный и инкрементальный Layout

      Скопировать ссылку «Глобальный и инкрементальный Layout» Скопировано

      Глобальный Layout — это процесс просчёта всего дерева полностью, то есть каждого элемента. Инкрементальный — просчитывает только часть.

      Глобальный Layout запускается, например, при изменении размера окна, потому что браузеру требуется подогнать всю страницу под новый размер экрана. Это очень дорогой процесс.

      Инкрементальный Layout запускает пересчёт только «грязных» элементов.

      «Грязные» элементы

      Скопировать ссылку ««Грязные» элементы» Скопировано

      Это те элементы, которые были изменены, и их дочерние элементы.

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

      Дерево «грязных» и перерисованных элементов

      Дальше браузер приступает к, собственно, отрисовке.

      Непосредственно отрисовка, Paint

      Скопировать ссылку «Непосредственно отрисовка, Paint» Скопировано

      Во время отрисовки (Paint) браузер наполняет пиксели на экране нужными цветами в зависимости от того, что в конкретном месте должно быть нарисовано: текст, изображение, цвет фона, тени, рамки и т. д.

      Отрисовка тоже бывает глобальной и инкрементальной. Чтобы понять, какую часть вьюпорта надо перерисовать, браузер делит весь вьюпорт на прямоугольные участки. Логика тут та же, как и в Layout — если изменения ограничены одним участком, то пометится «грязным» и перерисуется лишь он.

      Отрисовка — это самый дорогой процесс из всех, что мы уже перечислили.

      Порядок отрисовки

      Скопировать ссылку «Порядок отрисовки» Скопировано

      Порядок отрисовки связан со стековым контекстом.

      В общих чертах, отрисовка начинается с заднего плана и постепенно переходит к переднему:

      • background — color ;
      • background — image ;
      • border ;
      • children ;
      • outline .

      CPU и композитинг

      Скопировать ссылку «CPU и композитинг» Скопировано

      И Layout, и Paint работают за счёт CPU (central process unit), поэтому относительно медленные. Плавные анимации при таком раскладе невероятно дорогие.

      Для плавных анимаций в браузерах предусмотрен композитинг (Compositing).

      Композитинг — это разделение содержимого страницы на «слои», которые браузер будет перерисовывать. Эти слои друг от друга не зависят, из-за чего изменение элемента в одном слое не затрагивает элементы из других слоёв, и перерисовывать их становится не нужно.

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

      Схема композитинга

      Применение таких свойств, как, например, transform , «выносит» элемент на отдельный композитный слой, где положение элемента не зависит от других и не влияет на них.

      Чтобы узнать, вызывает ли конкретное CSS-свойство композитинг и перерисовку в браузере, воспользуйтесь инструментом «CSS Triggers».

      Перерисовка, Reflow (relayout) и Repaint

      Скопировать ссылку «Перерисовка, Reflow (relayout) и Repaint» Скопировано

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

      Если, например, в DOM-дереве добавился новый узел, или изменился текст, то браузер построит новое дерево рендеринга и запустит вычисление позиции и отрисовку заново.

      Один цикл обновления — это animation frame.

      Зная «расписание отрисовки» браузера, мы можем «предупредить» его, что хотим запустить какую-то анимацию на каждый новый фрейм. Это можно сделать с помощью request Animation Frame ( ) .

       const animate = () =>  // Код анимации> const animate = () =>  // Код анимации >      

      Эта функция запускает новый кадр анимации: обновляет какое-то свойство или перерисовывает canvas.

      Если мы хотим добиться плавной анимации, используя функцию выше, мы должны обеспечить в среднем 60 обновлений экрана за секунду (60 fps — frames per second).

      Это можно сделать топорно, через интервал:

       // 60 раз в 1000 миллисекунд, приблизительно 16 мс.const intervalMS = 1000 / 60setInterval(animate, intervalMS) // 60 раз в 1000 миллисекунд, приблизительно 16 мс. const intervalMS = 1000 / 60 setInterval(animate, intervalMS)      

      Либо использовать window . request Animation Frame ( ) :

       window.requestAnimationFrame(animate) window.requestAnimationFrame(animate)      

      Интервалы не всегда запускаются в нужный момент. set Interval ( ) не учитывает, на какой стадии отрисовки находится страница, и в итоге кадры отрисовки могут быть рваными или дёрганными.

      С интервалом анимация может быть рваной, потому что перерисовка может быть запущена в неподходящее время.

      А если вкладка была неактивна, то интервал может «попытаться догнать время», и несколько кадров запустятся разом:

      Анимация с setInterval

      С request Animation Frame ( ) анимация плавнее, потому что браузер знает, что в следующем фрейме надо запустить новый кадр анимации.

      Она не гарантирует, что анимация будет запущена строго раз в 16 мс, но значение будет достаточно близким.

      Анимация с requestAnimationFrame

      На практике

      Скопировать ссылку «На практике» Скопировано

      Саша Беспоясов советует

      Скопировать ссылку «Саша Беспоясов советует» Скопировано

      Для динамики всегда используйте transform и opacity , избегайте изменения остальных свойств (типа left , top , margin , background и так далее).

      Таким образом вы дадите браузеру возможность оптимизировать отрисовку, отчего страница станет отзывчивее.

      Для анимаций, которые необходимо перерисовывать на каждый фрейм, используйте request Animation Frame ( ) .

      Это сделает тяжёлую анимацию менее рваной.

      На собеседовании

      Скопировать ссылку «На собеседовании» Скопировано

      Что такое прогрессивный рендеринг (progressive rendering)?

      Скопировать ссылку «Что такое прогрессивный рендеринг (progressive rendering)?» Скопировано

      Скопировать ссылку «Марина Дорошук отвечает» Скопировано

      Чтобы понять что такое progressive rendering, нужно понимать отличие client-side rendering от server-side rendering.

      При client-side rendering (CSR) контент отрисовывается на стороне клиента (в браузере). Такой подход используется в React, когда браузеру отсылается практически пустой HTML-документ, а потом запускается скрипт, который генерирует HTML в указанном скрипту теге. Как правило это . Пользователь будет видеть пустую страницу, пока JS-файл полностью не загрузится.

      При server-side rendering (SSR) HTML-разметка генерируется на сервере, отсылается браузеру и после этого отрисовывается на клиенте. Пользователь увидит контент сразу же, но не сможет взаимодействовать со страницей, пока не загрузится JS-файл.

      При использовании прогрессивного рендеринга, кусочки HTML генерируется на сервере и отсылаются браузеру в порядке их приоритетности. То есть, элементы с самым высоким приоритетом (например , фон, главная интерактивная часть страницы) генерируются на сервере, отсылаются браузеру и отрисовываются в первую очередь. Это позволяет пользователю увидеть самый важный контент как можно скорее, не дожидаясь полной загрузки всего контента. То есть, progressive rendering что-то среднее между client-side rendering и server-side rendering.

      Техники реализации прогрессивного рендеринга:

      1. Ленивая загрузка (Lazy Loading). Загрузка контента по мере необходимости. Например, если страница достаточно большая, не нужно загружать изображения вне вьюпорта. Загрузка изображения стартует за некоторое время до того как она появится во вьюпорте. Эту же технику можно использовать для загрузки контента изначально скрытых элементов. Например, можно загрузить контент закрытого меню когда пользователь наводит курсор на кнопку открытия.
      2. Приоритизация контента. Например, не загружать изначально все CSS-стили. Добавлять в загрузку только тех стилей, которые нужны для текущей видимой области HTML-документа. Остальные стили можно добавить в .

      Как работают браузеры

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

      Чтобы понять, как улучшить производительность и ощущаемую пользователем производительность (User Perceived Performance, UPP), вам необходимо понимать, как работают браузеры.

      Обзор

      Быстрые приложения дают лучшие ощущения. Пользователи ожидают, что приложение будет грузиться быстро, а взаимодействие с ним будет плавным.

      Две главных проблемы в производительности — это проблема скорости сети и проблема однопоточности браузеров.

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

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

      Навигация

      Навигация — это первый этап при загрузке приложения. Он происходит каждый раз, когда пользователь запрашивает страницу, вводя URL в адресную строку браузера, нажимает на ссылку, отправляет заполненные поля формы и выполняет некоторые другие действия.

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

      DNS запрос

      Первый шаг навигации к странице — это поиск места, откуда нужно запрашивать данные. Если вы переходите на https://example.com , браузер грузит HTML-код страницы с IP-адреса 93.184.216.34 . Если вы никогда ранее не были на этом сайте, произойдёт поиск DNS записи.

      Ваш браузер запрашивает DNS запись. Как правило, запрос содержит имя сервера, который должен быть преобразован в IP-адрес. Ответ на этот запрос какое-то время будет сохранён в кеше устройства, чтобы его можно было быстро получить при следующем запросе к тому же серверу.

      DNS запрос обычно требуется совершить лишь единожды при загрузке страницы. Однако, DNS запросы должны быть выполнены для каждого уникального имени хоста, который запрашивается страницей. Скажем, если ваши шрифты, картинки, скрипты, реклама или счётчики аналитики находятся на разных доменах, DNS запрос будет осуществлён для каждого из них.

      Mobile requests go first to the cell tower, then to a central phone company computer before being sent to the internet

      Это может быть проблемой с точки зрения производительности, особенно для мобильных сетей. Когда пользователь находится в мобильной сети, каждый DNS запрос должен пройти от мобильного устройства до сотовой вышки, а уже оттуда дойти до авторитетного DNS-сервера. Расстояние и помехи между телефоном, вышкой и сервером имён могут значительно увеличить задержку.

      TCP Рукопожатие (Handshake)

      В тот момент, когда IP адрес становится известен, браузер начинает установку соединения к серверу с помощью рукопожатия TCP three-way handshake (en-US). Этот механизм спроектирован так, чтобы два устройства, пытающиеся установить связь, могли обменяться параметрами соединения, прежде чем приступать к передаче данных. Чаще всего — через защищённое соединение HTTPS.

      Трёхэтапное рукопожатие TCP — это техника, очень часто упоминаемая как «SYN-SYN-ACK» ( SYN, SYN-ACK, ACK , если быть точнее), т.к. при установке соединения передаются 3 сообщения. Это означает, что прежде чем установится соединение, браузер должен обменяться ещё тремя сообщениями с сервером.

      TLS Переговоры (Negotiation)

      Для установки безопасных соединений с использованием HTTPS требуется ещё одно рукопожатие. На этот раз — TLS переговоры. На этом шаге определяется, какой шифр будет использоваться для шифрования соединения, удостоверяется надёжность сервера и устанавливается безопасное соединение. Этот шаг также требует несколько дополнительных сообщений, которыми должны обменяться сервер и браузер, прежде чем данные будут посланы.

      The DNS lookup, the TCP handshake, and 5 steps of the TLS handshake including clienthello, serverhello and certificate, clientkey and finished for both server and client.

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

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

      Ответ на запрос

      Как только мы установили соединение с веб-сервером, браузер отправляет инициирующий HTTP GET запрос от имени пользователя. Чаще всего запрашивается HTML файл. В момент, когда сервер получает запрос, он начинает ответ с посылки заголовков ответа и содержимым HTML-файла.

      doctype html> html> head> meta charset="UTF-8" /> title>My simple pagetitle> link rel="stylesheet" src="styles.css" /> script src="myscript.js"> script> head> body> h1 class="heading">My Pageh1> p>A paragraph with a a href="https://example.com/about">linka>p> div> img src="myimage.jpg" alt="image description" /> div> script src="anotherscript.js"> script> body> html> 

      Этот ответ содержит в себе первый байт полученных данных. Время до первого байта (Time to First Byte, TTFB) — это время между моментом когда пользователь отправил запрос, скажем, нажав на ссылку, и моментом получения первого пакета данных HTML. Первый пакет обычно содержит 14КБ данных.

      В примере выше ответ значительно меньше, чем 14КБ; скрипты и стили, перечисленные в ответе, не будут запрошены, пока браузер не обработает ответ. Процесс обработки ответа — парсинг — мы обсудим отдельно.

      TCP медленный старт / правило 14kb

      Объём первого пакета данных — всегда 14KB. Это часть спецификации TCP slow start (en-US) — алгоритма, который балансирует скорость соединения. Такое правило позволяет постепенно, по мере необходимости, увеличивать размеры передаваемых данных, пока не будет определена максимальная ширина канала.

      В алгоритме TCP slow start (en-US) каждый следующий отправленный сервером пакет увеличивается в размере в два раза. Например, размер второго пакета будет около 28КБ. Размер пакетов будет увеличиваться до тех пор, пока не достигнет какого-то порогового значения или не упрётся в проблему переполнения.

      TCP slow start

      Если вы когда-то слышали о правиле 14КБ, то должны понимать, что оптимизация производительности загрузки должна учитывать ограничения этого начального запроса. Медленный старт TCP позволяет плавно ускорять передачу данных так, чтобы избежать проблемы переполнения, когда много данных ожидают отправки, но не отправляются из-за ограничений ширины канала.

      Контроль переполнения

      Любое соединение имеет ограничения, связанные с аппаратной и сетевой системами. Если сервер отправит слишком много пакетов за раз — они могут быть отброшены. Для того, чтобы избежать таких проблем, браузер должен реагировать на получение пакетов и подтверждать, что он получает их. Такой ответ-подтверждение называется Aknowledgements (ACK). Если из-за ограничений соединения браузер не получит данных, то он не пошлёт подтверждений ACK. В этом случае, сервер зарегистрирует, что какие-то пакеты не дошли и пошлёт их заново, что приведёт к лишней работе сервера и дополнительной нагрузке сети.

      Парсинг

      Как только браузер получает первый кусочек данных, он сразу начинает обрабатывать получаемую информацию. Эта обработка называется «Парсинг» (Parsing). Во время парсинга получаемые данные преобразуются в DOM и CSSOM (en-US), которые напрямую участвуют в отрисовке.

      DOM (Объектная модель документа) — это внутреннее представление разметки HTML. Браузер предоставляет доступ к манипуляции объектами этой модели через разные JavaScript API.

      Даже если ответ на запрос больше 14КБ, браузер всё равно начинает парсинг данных и пытается отрисовать страницу с теми данными, которые уже доступны. Именно поэтому при оптимизации производительности очень важно включать в инициирующий 14КБ ответ все необходимые для рендера данные — так браузер сможет быстрее начать формирование страницы. Однако, прежде чем что-либо появится на экране, HTML, CSS и JavaScript должны быть обработаны.

      Построение дерева объектной модели документа

      Мы уже рассказывали о пяти шагах в критическом пути рендеринга.

      Первый шаг — это обработка разметки HTML и построение дерева DOM. Обработка HTML включает в себя токенизацию и построение дерева. HTML-токены состоят из тегов старта и финиша, а также атрибутов. Если документ сформирован правильно, его обработка прямолинейна и быстра. Парсер (обработчик) преобразует входящие токены в документ и строит дерево документа.

      Когда парсер находит неблокирующие ресурсы (например, изображения), браузер отправляет запрос на загрузку ресурсов, но сам продолжает обработку. Обработка может продолжаться когда обнаружена ссылка на CSS файл, но если обнаружен , особенно если он без параметров async или defer — такой скрипт считается блокирующим и приостанавливает обработку HTML до завершения загрузки скрипта. Несмотря на то, что сканер предзагрузки (о нём ниже) браузера может находить и запрашивать такие скрипты заранее, сложные и объёмные скрипты всё ещё могут стать причиной заметных задержек загрузки страницы.

      Сканер предзагрузки

      Построение дерева DOM занимает весь поток процесса. Так как это явно узкое место в производительности, был создан особый сканер предзагрузки. Он обрабатывает доступное содержимое документа и запрашивает высокоприоритетные ресурсы (CSS, JavaScript и шрифты). Благодаря этому сканеру нам не нужно ждать, пока парсер дойдёт до конкретного места, где вызывается ресурс. Он запрашивает и получает эти данные заранее, в фоновом режиме, так что когда основной поток HTML-парсера доходит до запроса ресурса, высока вероятность, что ресурс уже запрошен или находится в процессе загрузки. Оптимизации, которые даёт этот сканер, уменьшают время блокирования рендера.

      link rel="stylesheet" src="styles.css" /> script src="myscript.js" async> script> img src="myimage.jpg" alt="image description" /> script src="anotherscript.js" async> script> 

      В примере выше основной поток обрабатывает HTML и CSS. В то же время, сканер предзагрузки находит скрипты и изображение и начинает их загрузку. Чтобы сделать скрипт неблокирующим, добавьте атрибут async или, в случае, если порядок загрузки скриптов важен, атрибут defer .

      Примечание: Ожидание получения CSS не блокирует парсинг HTML, но он блокирует JavaScript, потому что JavaScript часто используется для выборки узлов документа по CSS-селекторам.

      Построение модели стилей CSSOM

      Второй шаг при прохождении критического пути рендеринга — это обработка CSS и построение CSSOM дерева. CSSOM (объектная модель CSS) похожа на DOM. И DOM, и CSSOM — это деревья. Они являются независимыми структурами данных. Браузер преобразует CSS файлы в карту стилей, которую он может понять и с которой может работать. Браузер считывает каждый набор правил в CSS, создаёт дерево узлов с родителями, детьми и соседями, основываясь на CSS селекторах.

      Как и в HTML, браузер должен преобразовать полученные правила CSS во что-то, с чем он может работать. Таким образом, весь этот процесс — это повторение формирования DOM, только для CSS.

      CSSOM дерево включает в себя стили пользовательского агента — это стили, которые браузер вставляет по умолчанию. Браузер начинает построение модели с наиболее общих правил для каждого узла, постепенно применяя более специфичные правила. Другими словами, он применяет правила каскадно. Отсюда и название CSS — Cascading Style Sheets.

      Построение CSSOM происходит очень быстро и не отображается отдельным цветом в средствах разработчика. Оно настолько быстрое, что чаще всего включается в показатель «Повторное вычисление стилей (Recalculate Styles)» в средствах разработчика. Этот показатель показывает общее время обработки стилей — обработку CSS, построение CSSOM и рекурсивное вычисление стилей. С точки зрения оптимизации производительности здесь нечего делать, так как построение CSSOM, в целом, занимает даже меньше времени, чем DNS запрос.

      Остальные процессы

      Компиляция JavaScript

      Как CSS обработан и CSSOM создан, другие ресурсы, например, JavaScript-файлы, продолжают загружаться (спасибо сканеру предзагрузки). JavaScript по окончании загрузки должен быть интерпретирован, скомпилирован, обработан и исполнен. Скрипты преобразовываются в абстрактное синтаксическое дерево (AST). Некоторые браузеры берут Abstract Syntax Tree и передают его в интерпретатор, который преобразует дерево в байт-код. Байт-код исполняется в основном потоке. Весь этот процесс называется компиляцией.

      Построение дерева доступности

      Браузер также строит дерево доступности, которое используется устройствами-помощниками для понимания и интерпретирования контента. Объектная модель доступности (accessibility object model, AOM) — это семантическая версия DOM. Браузер обновляет AOM в тот же момент, когда обновляется DOM. В то же время, дерево доступности не может быть изменено вспомогательными технологиями.

      Пока модель AOM не построена, содержимое страницы недоступно для голосовых помощников и считывателей экрана (en-US) .

      Рендеринг

      Этапы рендеринга включают в себя стилизацию, компоновку (layout), отрисовку (paint) и, в некоторых случаях, композицию (composition). CSSOM и DOM деревья, созданные на предыдущем этапе комбинируются в дерево рендера, которое затем используется для расчёта положения каждого видимого элемента. После этого элементы будут отрисованы на экране. В некоторых случаях содержимое может быть вынесено на отдельные слои и совмещено (composition) — такой подход увеличивает производительность, позволяя отрисовывать содержимое экрана на графическом процессоре вместо ЦПУ. Это освобождает основной поток.

      Стилизация

      Третий шаг в критическом пути рендеринга — это комбинирование DOM и CSSOM в дерево рендеринга. Конструирование этого дерева начинается с прохода всего DOM-дерева от корня, с выявлением каждого видимого узла.

      Элементы, которые не должны быть показаны, например, , а так же их дети или любые элементы с display:none , такие как script < display: none; >, не будут включены в дерево рендера, так как они не должны быть отрисованы. Узлы с правилом visibility: hidden включены в дерево рендера, так как они всё равно занимают своё место. Так как мы не указали никаких специальных правил для перезаписи стилей агента по умолчанию, узел script в примере выше также не будет включён в дерево рендера.

      Каждый видимый узел имеет свои правила из CSSOM. Дерево рендера содержит все видимые узлы с их содержимым и вычисленными стилями. Стили определяются путём применения всех подходящих правил с использованием CSS каскада. (en-US)

      Компоновка (Layout)

      Четвёртый шаг на критическом пути рендеринга — это запуск компоновки (layout) элементов дерева рендера. На этом шаге вычисляется геометрия каждого узла, то есть ширина, высота, положение элементов. Reflow (перекомпоновка) — это любой последующий процесс определения размеров и позиции для любой из частей целого документа.

      Как только дерево рендера построено — начинается layout. Дерево несёт в себе информацию о том, какие узлы должны быть отрисованы (даже если они невидимы), и какие стили должны быть применены, но в дереве нет никакой информации о размерах и позиции элементов. Чтобы определить эти значения, браузер начинает обход дерева.

      На веб-странице практически все элементы прямоугольны (box). Разные устройства и настройки подразумевают бесчисленное количество разных размеров видимой области. На начальной фазе браузер, учитывая размер видимой области, определяет какие размеры разных элементов должны быть на экране. Использует размер видимой области как базис, процесс начинает вычисление с элемента body , затем переходит к его потомкам, вычисляет размеры каждого элемента и резервирует место для тех элементов, размеры которых он ещё не знает (например, изображения).

      Момент, когда позиция и размеры узлов вычислены, называется layout. Последующие вычисления позиций и размеров называются reflow. В нашем примере предполагаемый начальный layout происходит перед тем, как изображение получено. Так как мы не задавали размер изображения, в момент получения изображения произойдёт reflow.

      Отрисовка (Paint)

      Последний шаг критического пути рендеринга — это отрисовка каждого отдельного узла на экране. Момент, когда это происходит впервые, называется first meaningful paint (первая значащая отрисовка). Во время фазы отрисовки или растеризации, браузер конвертирует каждый контейнер box в настоящие пиксели на экране (напомним, что данные контейнеров формируются на этапе layout). Отрисовка подразумевает рисование каждой визуальной частицы элемента на экране (текст, цвета, границы, тени) и рисование заменяемых элементов (картинки, кнопки). Браузер должен выполнять это быстро.

      Чтобы обеспечить плавную прокрутку и анимацию, отрисовка каждого элемента занимает весь основной поток. Сюда включается вычисление стилей, повторное вычисление стилей и отрисовка. Все эти этапы должны выполняться не дольше 16.67 мс. (1000мс. / 60 кадров в секунду). При разрешении 2048х1536 экран iPad содержит 3.145.000 пикселей, которые должны быть отрисованы. Это много! Для того, чтобы сделать инициирующую и повторную отрисовки быстрее, можно разбить весь процесс на несколько слоёв. Когда это случается — становится необходима композиция.

      Отрисовка может разбить элементы в дереве рендера на слои. Для того, чтобы ускорить их рендер, браузер может перенести отрисовку разных слоёв на GPU (вместо основного потока CPU). Для переноса вычислений отрисовки на GPU вы можете использовать некоторые специальные HTML теги, например и ; а также CSS-свойства opacity , transform и will-change . Узлы, созданные таким образом, будут отрисованы на их собственном слое, вместе с их потомками, если только потомки сами по себе не будут вынесены в отдельные слои.

      Слои улучшают производительность. Но, с точки зрения управления памяти, они неэффективны. Поэтому старайтесь не использовать их там, где в них нет необходимости.

      Композиция (Compositing)

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

      При догрузке ранее запрошенных ресурсов (например, изображений) может потребоваться перерассчитать размеры и положение элементов относительно друг друга. Этот перерасчёт — reflow — запускает перерисовку (repaint) и перекомпозицию (re-composite). Если мы заранее определили размер изображения, перерасчёт не будет необходим и в этом случае только тот слой, который должен быть перерисован — будет перерисован. Но если мы не определили размер изображения заранее, то браузер, после получения ответа от сервера, будет вынужден отмотать процесс рендеринга обратно к шагу компоновки (layout) и начать процесс отрисовки ещё раз.

      Интерактивность

      Можно было бы подумать, что как только основной поток завершает отрисовку страницы — «всё готово». Это не всегда так. Если среди загружаемых ресурсов есть JavaScript, загрузка которого была корректно отложена, а запуск которого происходит только после события onload (en-US) , основной поток начинает обработку скриптов. Во время этой обработки браузер не может обрабатывать события прокрутки, нажатий и др.

      Time to Interactive (TTI, время до интерактивности) — это показатель того, как много времени проходит между самым первым сетевым запросом и моментом, когда страница становится интерактивной. В хронологии этот этап следует сразу за First Contentful Paint. Интерактивностью называется показатель того, что страница отреагировала на действие пользователя за время в 50мс. Если процессор занят обработкой, компиляцией и выполнением JavaScript, то браузер не может отреагировать достаточно быстро, а значит страница считается не интерактивной.

      В нашем примере, даже несмотря на то, что изображение загрузилось быстро, скрипт anotherscript.js , размер которого достигает 2МБ, загружается долго. В этом случае пользователь увидит страницу очень быстро, но не будет способен взаимодействовать с ней, пока скрипт не будет загружен, обработан и исполнен. Это плохая практика. Старайтесь избегать полной загрузки процесса.

      The main thread is occupied by the downloading, parsing and execution of a javascript file - over a fast connection

      В примере выше загрузка содержимого DOM заняла около 1.5 секунд. Все это время основной поток процесса был полностью загружен и не был способен обработать пользовательский ввод.

      Смотрите также

      Found a content problem with this page?

      • Edit the page on GitHub.
      • Report the content issue.
      • View the source on GitHub.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *