Браузеры стали частью нашей повседневной жизни. Но задумывались ли вы когда-нибудь о том, как они на самом деле работают?
Эта статья приоткроет завесу магии, скрывающуюся за кулисами веб-браузеров.
Давайте начнем!
1. Навигация
Навигация - это первый шаг загрузки веб-страницы. Она происходит когда пользователь вводит URL в адресной строке или делает клик по ссылке.
DNS-поиск
Первый шаг - найти IP-адрес, где располагаются ресурсы. Это делается с помощью DNS-поиска.
DNS (Domain Name System)-сервер - это сервер, который главным образом используются для сопоставления имени хоста веб-сайта (пр.: www.example.com) с соответствующим ему IP-адресом. Он содержит базу данных публичных IP-адресов и им соответствующих доменных имен.
Например если вы посетите страницу www.example.com, то DNS-сервер вернет вам ее IP-адрес (93.184.216.34).
Тройное TCP-рукопожатие
Следующий шаг - установить с сервером TCP-соединение. Это делается благодаря тройному TCP-рукопожатию.
Примечание переводчика. Transmission Control Protocol (TCP) - протокол управления передачей. Это стандарт, определяющий порядок установления и поддержания сетевого взаимодействия, с помощью которого приложения могут обмениваться данными.
- Сперва клиент посылает запрос на открытие соединения с сервером с помощью SYN-пакета (от англ. SYNchronize packet - пакет синхронизации).
- Затем сервер отвечает SYN-ACK-пакетом (от англ. SYNchronize-ACKnowledge packet - пакет синхронизации и подтверждения) чтобы подтвердить запрос и запросить клиента открыть соединение.
- В конце клиент посылает ACK-пакет на сервер для подтверждения запроса.
TLS-рукопожатие
Если веб-сайт использует протокол HTTPS (аббр. от англ. Hypertext Transfer Protocol Secure - защищенный протокол передачи гипертекста), то следующий шаг - установить TLS-соединение через TLS-рукопожатие.
Примечание переводчика. TLS (аббр. от англ. Transport Layer Security - защита транспортного уровня) - шифрует данные, передаваемые через Интернет, чтобы подслушивающие устройства и хакеры не могли увидеть то, что вы передаете, что особенно полезно для частной и конфиденциальной информации, такой как пароли, номера кредитных карт и личная переписка.
На этом этапе между браузером и сервером происходит обмен еще несколькими сообщениями.
- Клиент отправляет "привет": браузер отправляет серверу сообщение с версией TLS и набором шифров, которые он поддерживает, а также строку рандомных байтов именуемую «рандомом клиента» (client random).
Примечание переводчика. «Рандом клиента» (как и далее «рандом сервера») — это строка из 32-ух рандомных байтов. В соответствии со спецификацией TLS 1.2 первые 4 байта являются текущей датой и временем, а остальные 28 байтов — рандомно сгенерированными цифрами.
- Сервер отправляет «привет» и сертификат: в ответ на «привет» клиента сервер отправляет свое приветствующее сообщение содержащее SSL‑сертификат, набор шифров и строку рандомных байтов именуемую «рандомом сервера» (server random).
- Аутентификация: браузер проверяет SSL‑сертификат полученный от сервера на подлинность через «центр сертификатов», который его выпустил. Таким образом браузер может понять что сервер действительно является тем за кого он себя выдает.
- «Секрет премастера» (premaster secret): браузер отправляет еще одну строку рандомно сгенерированных байтов именуемую «секретом премастера», которая зашифрованна публичным ключом (public key) полученным из SSL‑сертификата сервера. «Секрет премастера» может быть расшифрован только с использованием приватного ключа (private key) сервера.
- Использование приватного ключа: сервер расшифровывает «секрет премастера».
- Создание ключей сессии: браузер и сервер генерируют ключи сессии на основе «рандома клиента», «рандома сервера» и «секрета премастера».
- Клиент завершает процесс рукопожатия: браузер отправляет серверу сообщение о завершении процесса.
- Сервер завершает процесс рукопожатия: сервер также отправляет клиенту сообщение о завершении процесса со своей стороны.
- Достигнута безопасность симметричного шифрования: рукопожатие выполнено и дальнейшая коммуникация может продолжиться с использованием ключей сессии (session keys).
Теперь можно начать отправлять запросы на сервер и получать от него данные.
2. Фетчинг ресурсов
После того как установлено TCP-соединение браузер может начать фетчинг (от англ. гл. to fetch - получать, загружать) ресурсов сервера.
HTTP-запрос
Если у вас уже есть опыт в веб-разработке, то вы наверняка встречали понятие HTTP-запросов.
HTTP-запросы используются для фетчинга ресурсов сервера. Для запросов необходимо указать URL и тип запроса (GET, POST, PUT, DELETE). Браузер также добавляет заголовки (headers) к запросу, что бы предоставить дополнительную информацию.
Первый запрос к серверу обычно является GET-запросом на получение HTML-файла.
HTTP-ответ
Затем сервер отвечает соответствующим HTTP-ответом. Ответ содержит код состояния (status code), заголовки (headers) и тело ответа (body).
3. Парсинг HTML
Теперь начинается главная секция. После того как браузер получил HTML-файл он парсит (от англ. гл. to parse - разбирать, анализировать) его для создания DOM (Document Object Model)-дерева.
Это делается при помощи движка браузера, который является его ядром (Пр.: Gecko для Firefox, Webkit для Safari, Blink для Chrome и т.д.).
Вот пример HTML-файла:
Токенизация
Первый шаг на пути к отображению веб-страницы - это токенизация HTML-файла. Токенизация - это процесс деления строки символов на значимые чанки (от англ. chunk - кусок) для браузера, именуемые токенами (от англ. token - жетон).
Токены являются базовыми строительными блоками DOM-дерева.
Строительство DOM-дерева
Лексинг (lexing) - это процесс конвертации токенов в древовидную структуру именуемую DOM-деревом.
DOM-дерево - это древовидная структура данных, которая представляет собой ноды(от англ. node - узел) в HTML-документе.
Заметка: если для страницы требуются какие-либо внешние ресурсы, то они будут обработаны следующим образом:
- Не блокирующие ресурсы загружаются параллельно (Пр.: картинки)
- Отложенные ресурсы загружаются параллельно, но выполняются после того как будет построено DOM-дерево. Пр.: скрипты с атрибутом defer и CSS-файлы.
- Блокирующие ресурсы загружаются и выполняются последовательно. Пр.: скрипты БЕЗ атрибута defer.
4. Парсинг CSS
После того как DOM-дерево построено, браузер парсит CSS-файлы для создания CSSOM (CSS Object Model).
Этот процесс аналогичен построению DOM-дерева с использованием токенизации и генерации CSSOM.
5. Выполнение JavaScript
Как упоминалось ранее, если у страницы есть блокирующий скрипт, то он будет загружен и обработан незамедлительно, в то время как строительство DOM-дерева будет отложено, либо же скрипт будет загружен и выполнен после того, как DOM-дерево будет полностью создано.
Независимо от того когда выполняется скрипт, он будет обработан движком JavaScript, который похож на движок браузера и зависит от того какой браузер используется.
JIT-компиляция
Предполагая, что вам уже знакома концепция интерпретаторов и компиляторов, поговорим о движке JavaScript.
Движок JavaScript использует гибридный подход компиляции именуемый JIT (от англ. аббревиатуры Just in Time - точно в срок).
JIT-компиляция, в отличие от скомпилированного языка такого как C, где компиляция делается заранее (другими словами ДО выполнения кода), делается ВОВРЕМЯ выполнения.
6. Рендеринг
Наконец-то пришло время рендера (от англ. rendering - визуализация) страницы. Для рендеринга браузер использует DOM-дерево и CSSOM.
Построение дерева рендера
Первый шаг - построить дерево рендера. Дерево рендера - это подмножество DOM-дерева, состоящее только из видимых на странице элементов.
Компоновка (layout)
Следующим этапом является компоновка дерева рендера. Она делается путем расчетов точных размеров и позиции каждого элемента в дереве рендера.
Этот этап происходит каждый раз, когда мы изменяем что-нибудь в DOM, что затрагивает компоновку страницы, даже частично.
Примеры ситуаций, когда позиция элементов перерассчитывается:
- Добавление или удаление элементов из DOM
- Изменение размеров окна браузера
- Изменение ширины, высоты или позиции элемента
Отрисовка (painting)
Наконец, браузер решает, какие ноды должны быть видимыми, и рассчитывает их позицию в области просмотра (viewport), после чего наступает время их отрисовать (сделать рендер пикселей) на экране. Этот этап также известен как этап растеризации, на котором браузер преобразует каждый элемент, рассчитанный на этапе компоновки, в реальные пиксели на экране.
Также как и этап компоновки, этот этап происходит каждый раз когда мы изменяем отображение элемента в DOM, даже частично.
Примеры ситуаций, когда происходит повторная отрисовка:
- Изменение очертания элемента
- Изменение прозрачности (opacity) или видимости (visibility) элемента
- Изменение цвета фона элемента
Наложение слоев и композиция
Финальный этап - композиция слоев. Это делается браузером для оптимизации процесса рендеринга.
Композиция (compositing) - это техника разделения частей страницы на слои, их отрисовки и дальнейшего составления из них страницы в отдельном потоке называемом композиторским потоком (compositor thread). Когда разделы документа рисуются в разных слоях, перекрывая друг-друга, композиция необходима для того что бы удостовериться, что они нарисованы в правильном порядке и их содержимое корректно отображается.
Заметка: обновления DOM, в частности компоновка и отрисовка, чрезвычайно ресурсоемкие операции, которые существенно заметны на слабых устройствах. Поэтому важно минимизировать количество их срабатываний.
На этом все!
Спасибо за прочтение.
Теги:
Хабы: