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

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

Другое 22.07.2019

Основное предназначение браузера – отображение запрашиваемых ресурсов. Расположение ресурса определяется с помощью URI (унифицированого идентификатора ресурса).

Рассмотрим основные компоненты браузера:

Browser Components
  1. User Interface (Пользовательский интерфейс)– адресная строка, кнопки “Вперед”/”Назад” и остальные элементы, через которые пользователь может взаимодействовать с браузером.
  2. Browser Engine (Механизм браузера) – управляет взаимодействием User Interface и Rendering Engine
  3. Rendering Engine (Модуль отображения) – выполняет синтаксический анализ кода запрашиваемого ресурса и выводит содержимое на экран. По умолчанию он отображает HTML, XML документы и картинки, для отображения других файлов, например pdf, используются специальные модули. В Chrome и Safari модулем отображения является Webkit, а в Firefox – Gecko. Подробней о работе Rendering Engine рассмотрим далее.
  4. Networking (Сетевые компоненты) – выполнение сетевых вызовов (HTTP запросы)
  5. UI Backend – отрисовка основных виджетов – окна, поля со списками.
  6. Интерпретатор JS – синтаксический анализ и выполнение JS
  7. Data Persistence (Хранилище данных) – браузер хранит данные в формате “ключ: значение” на жестком диске для различных сайтов (cookie, sessionStorage).

Что же происходит когда мы ищем нужный ресурс в браузере?

google search home page

Когда пользователь вводит данные в адресной строке, браузер, получив строку к примеру “searchpage.com.ua”, должен узнать IP-адрес. User Interface после ввода url передает управление элементу Browser Engine. Для того, что бы сделать запрос по указанному в адресной строке url, браузеру нужно узнать адрес IP сервера.

Компьютеры в сети интернет имеют доменное имя (например, site.com) и IP-адрес (например, 127.0.0.1). Основной задачей DNS сервера является трансляция доменных имен в IP-адреса и обратно. DNS имеет иерархическую структуру имен, где есть корень дерева (“.”), далее расположены домены первого уровня (com, net, org и т.д.) и домены государств (ua, ru и т.д.), далее домены второго, третьего уровня… Когда клиент посылает запрос этому серверу, сервер или отвечает на запрос (если знает ответ) или пересылает запрос вышестоящему серверу, а когда ответ найден он опускается низ по цепочке серверов к источнику запроса. Процесс получения IP адреса называется DNS lookup.

Для того, что бы узнать IP-адрес ресурса “searchpage.com.ua” начинается поиск с локального кеша DNS и с локальных хостов (файл /etc/hosts), если там запись не найдена – локальная система обращается к интернет провайдеру, который тоже имеет свой кеш DNS, если и там не найден – запрос идет дальше по цепочке серверов.

В нашем примере для сайта “searchpage.com.ua” запросы будут идти приблизительно так: . (корневой DNS) -> ua (DNS зоны “ua”) -> com (DNS зоны “com”)-> searchpage.

Далее Browser Engine смотрит, нет ли в ее кеше данных соответвующих ресурсу по искомому IP-адресу, если такого закешированого ресурса не найдено – передается управление Rendering Engine, который, при помощи компонента Network, посылает GET запросы за ресурсом HTML на указанный IP. Браузер получает запрашиваемый HTML файл с указанными заголовками, если присутствуют заголовки для кеширования – он сохранит их в свой локальный кеш. Далее браузер начинает парсинг полученного ресурса при помощи Rendering Engine.

Модуль отображения (Rendering Engine)

Rendering Engine получает содержимое запрашиваемого документа обычно фрагментами по 8 КБ.
Сначала он проводит синтаксический анализ и парсинг HTML документа и приводит параметры в узлы для построения DOM дерева (Дерева содержания). СSS документы тоже обрабатываются и служат для построения CSSOM дерева, а так же там собирается вся информация о стилях, найдена в других источниках, например, inline стили в html. После DOM дерево и CSSOM дерево объединяются в одно, этот процесс называется Attachment, для создания Render Tree. Дерево отображения (Render Tree) состоит из объектов отображения (Render Objects). В нем элементы отображения располагаются в том порядке в котором их необходимо вывести на экран.
Из полученного Render Tree происходит компоновка (layout), в процессе которой каждому узлу дерева отображения присваиваются координаты места, где он должен появится. Затем с помощью UI Backend происходит отрисовка элементов.

Ниже представлена схема работы модуля отображения WebKit:

webkit Rendering Engine

Синтаксический анализ HTML

Синтаксический анализ – это преобразование документа в пригодную для чтения структуру. Результатом синтаксического анализа является дерево узлов, представляющее структуру документа – Синтаксическое дерево. В случае анализа HTML документа – в результате синтаксического анализа мы получим синтаксическое дерево (DOM).

Объектная модель документа (DOM) – это фундаментальный прикладной программный интерфейс, обеспечивающий возможность работы с содержимым HTML & XML документов таким внешним объектам как код JS.

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

DOM состоит из узлов, представляющих элементы или теги, такие как <p> или <body>, и узлы представляющие строки текста.

Рассмотрим пример как бы выглядело DOM дерево для такого html кода:

<html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <p>Demo Text</p>
        <div>
            <img src="example.png">
        </div>
    </body>
</html>
DOM

Каждый прямоугольник, представленный на DOM дереве является объектом Node. На схеме представлены узлы типа Document, Element (p, div …) и Text – они являются подклассами класса Node.

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

Порядок обработки CSS & JS

Обработка CSS

При обработке стилей браузер строит подобную древовидную структуру, как было рассмотрено выше. В файле стилей имеется селектор (div, #id, .cssClass) и значение. Браузер читает селекторы справа налево, например, селектор типа div ul > a будет обработан в такой поочередности: сначала браузер найдет все элементы a на странице, после ul и отфильтрует массив ul до тех, дочерними элементами которых являются a и т.д. пока не дойдет до крайнего левого селектора.

В результате синтаксического анализа CSS будет построено дерево на основе всех найденных стилей, рассмотрим маленький пример:

body {
    font-size: 16px;
}

h1 {
    text-align: center;
}

В следствии обработки такого css будет построено CSSOM дерево:

cssom tree

После построения дерева CSS браузеру нужно сопоставить его с DOM деревом элементов. В Webkit процесс сопоставления DOM дерева и стилей называется Attachment. Совмещение происходит синхронно – при добавлении нового элемента DOM дерева для него вызывается метод attach.

Обработка Javascript

Javascript код выполняется сразу как был обнаружен на странице тег <script>, при этом синтаксический анализ документа останавливается до выполнения скрипта. Если речь идет о внешних источниках, которые нужно загрузить, синтаксический анализ документа точно так же ставится на паузу, но уже для загрузки и выполнения кода.
Чтобы влиять на время выполнения скрипта, можно использовать атрибуты defer или async. Они позволяют не останавливать синтаксический анализ документа для загрузки скрипта.

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

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

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

Если присутствуют оба атрибута – defer будет проигнорирован.

Так как стили не вносят изменение в DOM – останавливать синтаксическую обработку для их загрузки нет необходимости, но скрипты JS могут пытаться использовать еще не загруженные стили, таким образом в WebKit скрипты останавливаются только в том случае, если просят данные о стилях, а браузер имеет в наличии еще необработанные таблицы стилей, а Gecko останавливает все скрипты если обнаруживает, что какая-то таблица стилей была еще не обработана.

Render Tree

Во время обработки HTML и CSS создается еще одно дерево – дерево отображения или Render Tree, в котором элементы располагаются в том порядке. в котором они будут выведены на экран. Render Tree состоит из объектов отображения, которые в свою очереди представляют из себя прямоугольную область, где содержатся геометрические данные – высота, ширина, размеры рамок и отступов. Тип окна объекта отображения зависит от свойства display.

render Object

Один объект синтаксического DOM дерева может иметь 1 или больше объектов дерева отображения, так к примеру элемент select будет иметь 3 объекта дерева отображения – объект отображения области, раскрывающийся список и кнопка. Стоит отметить, что если текст не помещается в одну строку – каждой строке будет создан новый объект отображения. Элементам со стилем display: none не будет создано объекта отображения в Render Tree.

Для построения дерева стилей нужно рассчитать свойство каждого элемента, достав стили с внешних файлов, inline стилей и стилей заданных атрибутами (например width, bgcolor…).

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

Layout – это расчет размера и положения объекта.
В большинстве случаев компоновка выполняется за 1 проход, так как последующие элементы не влияют на размеры уже рассчитанных элементов, но бывают и исключения, к примеру таблицы.
Layout проходит в несколько циклов и начинается с объекта html, который получает начальные координаты 0:0, а размеры соответствуют видимой части экрана.

Существует 2 вида компоновки – инкрементная и глобальная. Глобальная компоновка выполняется для всего Render Tree, а инкрементная только для части Render Tree – тех объектов которые помечены как “dirty”.

Что бы не выполнять глобальную перекомпоновку при небольших изменениях была придумана система “грязных битов” – измененный объект отображения и его дочерние элементы помечаются флагами dirty и children are dirty. Флаг children are dirty означает, что перекомпоновка нужна не самому объекту, а одному из его дочерних элементов.

Глобальную перекомпоновку могут вызвать какие-то глобальные изменения, которые используются во всех объектах, например, изменение шрифта или размеров экрана.
Инкрементная перекомпоновка выполняется асинхронно по мере обнаружения “грязных битов”.

Способ компоновки окна определяется следующими способами:

  • Типом окна
  • Размером окна
  • Схемой позиционирования
  • Внешней информацией (например размеры экрана)

Тип окна элементов отображения зависят от свойства display: block, inline, none. Блочное окно имеет собственный блок, строчное окно не имеет собственного блока и помещается внутрь контейнера,
В зависимости от свойств position и float существуют разные схемы позицинирования:

  • Стандартная – объект размещается в документе согласно своему положению в дереве
  • Плавающая – сначала объект размещается в документе согласно своему положению в дереве, а после сдвигается в крайнее левое или крайнее правое положение
  • Относительная – положение объекта в дереве отображения отличается от его положения в дереве DOM

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

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

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

Источники:
“How browsers work” By Tali Garsiel and Paul Irish
“Javascript. Подробное руководство” Дэвид Флэнаган
Medium
Blog imena.ua

Поделиться

2
Отправить ответ

avatar
1 Comment threads
1 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
MelineКобжев Андрей Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Кобжев Андрей
Гость
Кобжев Андрей

Хорошая статья.