JavaScript

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

Spread the love

Перевод: James StarkieHow the browser renders a web page

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


Много идей основано на фантастическом (и БЕСПЛАТНОН!) курсе по оптимизации производительности веб-сайта Website Performance Optimization Ilya Grigorik и Cameron Pittman на Udacity. Я очень рекомендую это посмотреть.

Также очень полезной оказалась статья Пола Айриша и Тали Гарсиэль How Browsers Work: Behind the scenes of modern web browsers. Хотя эта статья 2011 года, но многие основы работы браузеров остаются актуальными до сих пор.

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

  1. Начало разбора HTML
  2. Получение внешних ресурсов
  3. Разбор CSS и создание CSSOM
  4. Выполнение JavaScript
  5. Объединение DOM и CSSOM, для построения дерево рендеринга
  6. Расчет макета и отрисовка результата

1. Начало разбора HTML

Когда браузер начинает получать данные HTML страницы по сети, он немедленно запускает свой синтаксический анализатор parser для преобразования HTML в объектную модель документа (DOM) Document Object Model (DOM).

Объектная модель документа (DOM) — это представление данных объектов, которые составляют структуру и содержимое документа в Интернете.

Первый шаг этого процесса синтаксического анализа — разбить HTML на токены, которые представляют начальные теги (start tags), конечные теги (end tags) и их содержимое (contents). Из этого он строит DOM.

2. Получение внешних ресурсов

Когда парсер встречает внешний ресурс, такой как файл CSS или JavaScript, он пытается, получить его. Синтаксический анализатор будет продолжать работу по мере загрузки файла CSS, но он заблокирует рендеринг до тех пор, пока файл не будет загружен и проанализирован (подробнее об этом чуть позже).

Файлы JavaScript немного отличаются — по умолчанию они так же блокируют синтаксический анализ HTML, на время загрузки. Но у них есть два атрибута, которые могут быть добавлены в теги сценария, чтобы изменить это: defer и async. Оба позволяют синтаксическому анализатору продолжать работу, пока файл JavaScript загружается в фоновом режиме. Они отличаются друг от друга то, как они выполняются. Подробнее об этом тоже немного ниже, но вкратце:

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

<script type="text/javascript" src="script.js" defer>

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

<script type="text/javascript" src="script.js" async>

Предварительная загрузка ресурсов

Кроме того, современные браузеры будут продолжать сканировать HTML-код, пока анализатор блокирован, и «смотреть вперед» на то, какие внешние ресурсы появляются, а затем загружать их предположительно. То, как они это делают, варьируется в зависимости от браузера, поэтому нельзя полагаться на то, что они будут вести себя определенным образом. Чтобы пометить ресурс как важный и, следовательно, с большей вероятностью он должен быть загруженным на ранней стадии процесса рендеринга, можно использовать тег ссылки с rel = «preload».

<link href="style.css" rel="preload" as="style" />

3. Разбор CSS и создание CSSOM

Возможно, вы слышали о DOM, но слышали ли вы о CSSOM (CSS Object Model) (объектной модели CSS)? До того, как я начал исследовать эту тему, я об этом ни чего не знал!

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

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

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

Чем CSSOM отличается от DOM, так это тем, что он не может быть построен постепенно, поскольку правила CSS могут перезаписывать друг друга в разных точках из-за specificity (порядка применения свойства). Вот почему загрузка CSS блокирует рендеринг, поскольку до тех пор, пока весь CSS не будет проанализирован и не будет построен CSSOM, браузер не может знать, где и как разместить каждый элемент на экране.

4. Выполнение JavaScript

Как и когда ресурсы JavaScript будут загружены, определяет, в какой-то момент они будут проанализированы, скомпилированы и выполнены. В разных браузерах для выполнения этой задачи используются разные механизмы JavaScript. Анализ JavaScript может быть дорогостоящим процессом с точки зрения ресурсов компьютера, в большей степени, чем другие типы ресурсов, поэтому его оптимизация так важна для достижения хорошей производительности. Прочтите этот фантастический пост, чтобы подробнее узнать, как работает движок JavaScript.

События загрузки

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

document.addEventListener('DOMContentLoaded', (event) => {
    // You can now safely access the DOM
});

После того, как все остальное, например асинхронный JavaScript, изображения и т. д., завершили загрузку, запускается событие window.load.

window.addEventListener('load', (event) => {
    // The page has now fully loaded
});

5. Объединение DOM и CSSOM, для построения дерево рендеринга

Дерево рендеринга представляет собой комбинацию DOM и CSSOM и представляет все, что будет отображаться на странице. Это не обязательно означает, что все узлы в дереве рендеринга будут визуально присутствовать, например узлы со стилями opacity: 0 или visibility: hidden будут включены и могут быть прочитаны программой чтения с экрана и т. д., тогда как те, которые настроены на display: none будет исключены. Кроме того, такие теги, как <head>, не содержащие визуальной информации, всегда будут пропущены.

Как и в случае с движками JavaScript, разные браузеры имеют разные механизмы рендеринга.

6. Расчет макета и отрисовка результата

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

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

И вуаля! В конце концов, у нас есть полностью отрисованная веб-страница!

Была ли вам полезна эта статья?
[60 / 4.8]

Spread the love
Editorial Team

View Comments

  • Синтаксический анализ завершится первым и произойдет рендеринг перед тем, как выполнится async скрипт, даже если он был в кэше браузера

    • Не соглашусь, в js есть даже события, которые можно отслеживать, DOMContentLoaded и load. И первый, к примеру, отрабатывает когда заканчивается парсинг html, что сигнализирует о том, что js код в это время уже выполняется)

      • Он отрабатывает, но только если js подключен не через async\defer

  • Очень бегло автор прошелся по Layout, Paint, Composition, а это важно

Recent Posts

Vue 3.4 Новая механика v-model компонента

Краткий перевод: https://vuejs.org/guide/components/v-model.html Основное использование​ v-model используется для реализации двусторонней привязки в компоненте. Начиная с Vue…

12 месяцев ago

Анонс Vue 3.4

Сегодня мы рады объявить о выпуске Vue 3.4 «🏀 Slam Dunk»! Этот выпуск включает в…

12 месяцев ago

Как принудительно пере-отобразить (re-render) компонент Vue

Vue.js — это универсальный и адаптируемый фреймворк. Благодаря своей отличительной архитектуре и системе реактивности Vue…

2 года ago

Проблемы с установкой сертификата на nginix

Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с…

2 года ago

Введение в JavaScript Temporal API

Каким бы ни было ваше мнение о JavaScript, но всем известно, что работа с датами…

2 года ago

Когда и как выбирать между медиа запросами и контейнерными запросами

Все, кто следит за последними событиями в мире адаптивного дизайна, согласятся, что введение контейнерных запросов…

2 года ago