Основы веба, которые должен знать начинающий разработчик
В этом посте я объясню, как работает Интернет. Мы ответим на вопросы наподобие «Как браузер находит файл HTML для запрошенной веб-страницы?», «Как файл HTML превращается в интерфейс пользователя?», «Что можно сделать, чтобы ускорить этот процесс?», «Как устанавливается и поддерживается связь с сервером?», а также рассмотрим следующие концепции:
- Клиент-серверную модель
- Жизненный цикл запроса веб-страницы
- Hypertext Transfer Protocol
- Как браузеры рендерят контент
Клиент-серверная модель
Термин «клиент-серверная модель» — это обобщённое понятие, описывающее взаимодействие друг с другом двух компьютеров; один из компьютеров является клиентом, запрашивающим информацию, другой — сервером, отправляющим эту информацию. Эту модель можно использовать во множестве различных проектов, и одним из самых популярных примеров его применения является Интернет.
Когда мы пытаемся перейти на какой-нибудь веб-сайт, допустим, на linkedin.com, то наш браузер превращается в клиент. Он выполняет запрос к серверу. Сервер создаётся LinkedIn. Когда кто-то создаёт веб-сайт, он должен содержать этот веб-сайт на каком-то сервере. Иногда для этого используется поставщик облачных услуг наподобие AWS или Azure, или же можно создать сервер самостоятельно.
Сервер будет отправлять клиенту HTML, после чего клиент, который, повторюсь, является обычным веб-браузером, интерпретирует этот HTML и генерирует пользовательский интерфейс. Пока вы продолжаете пользоваться linkedin.com и взаимодействовать со страницей, браузер продолжает обмениваться данными с сервером.
Иногда один компьютер может быть в двух разных взаимодействиях и клиентом, и сервером. Например, одна машина может быть сервером для конечных пользователей и клиентом для базы данных.
Жизненный цикл запроса веб-страницы
Что же происходит, когда мы переходим на linkedin.com? Что делает браузер, чтобы запросить HTML для этой страницы с сервера LinkedIn? Чтобы ответить на эти вопросы, нам сначала нужно взглянуть на её URL. Полный URL может выглядеть примерно так: https://www.linkedin.com:443/feed . Давайте его разберём.
- HTTPS — это протокол, определяющий, как будет отформатирован этот запрос. HTTPS и HTTP — это стандартные протоколы для обмена данными в Интернете.
- После протокола идут двоеточие и две косые черты, затем поддомен, а также доменное имя. linkedin.com — это доменное имя, а также имя веб-сайта. www — это поддомен, его можно воспринимать как домен внутри домена linkedin. Доменное имя разбито на имя веб-сайта и домен верхнего уровня, то есть часть .com . Большинство доменов верхнего уровня связано с какой-нибудь страной.
- Далее указан порт 443 , который можно не указывать, потому что это стандартный порт. Для HTTPS по умолчанию используется порт 443, а для HTTP — 80. В URL почти никогда не требуется указывать порт.
- Затем идёт путь к ресурсу, который мы запрашиваем. Если вы просто запрашиваете домашнюю страницу, то большинство серверов позволяет не указывать путь. Однако если вам нужен конкретный ресурс, например, лента новостей LinkedIn, то нужно будет добавить косую черту и путь feed .
Разобравшись с URL, нам нужно найти сервер и отправить ему запрос HTML. Когда вам нужно отправить запрос к серверу, вы знаете, что его доменное имя linkedin.com, но необходимо ещё и определить адрес этого сервера. Его можно узнать при помощи IP-адреса. Это уникальный идентификатор компьютера в Интернете. Для поиска IP-адреса нужного домена используется Domain Name System (DNS, система доменных имён).
Когда браузер ищет IP-адрес веб-сайта, сначала он проверяет локальный кэш. Операционная система на вашей машине хранит локальный кэш каждого IP-адреса, который недавно был обнаружен при помощи DNS. Благодаря этому, ей не приходится выполнять повторные сетевые запросы. Если IP-адрес не найден в локальном кэше, в сеть передаётся DNS-запрос.
Сначала этот запрос передаётся на сервер ресолвинга имён, который проверяет собственный кэш. Сервер ресолвинга имён (resolving name server) обычно принадлежит вашему Интернет-провайдеру. Далее, если сервер ресолвинга имён не знает IP-адреса, то он будет искать корневой сервер имён. На этом сервере хранятся сопоставления доменов верхнего уровня наподобие .com с IP-адресами серверов доменных имён верхнего уровня. Для каждого домена верхнего уровня существует сервер, который знает, как найти IP-адреса всех доменов, зарегистрированных в этом домене верхнего уровня.
Корневой сервер имён может сообщить серверу ресолвинга имён, где искать, и где находится сервер домена верхнего уровня. Сервер ресолвинга имён использует эту информацию для выполнения запроса к нужному серверу доменных имён верхнего уровня (серверу имён TLD). Мы достигли сервера доменов верхнего уровня, который перенаправит нас на полномочный сервер имён. Полномочный сервер имён (authoritative name server) знает IP-адрес домена, который мы ищем, поэтому он отправит этот IP-адрес серверу ресолвинга имён, который, в свою очередь, вернёт его вашему компьютеру, и браузер будет знать, где искать.
Теперь мы знаем IP-адрес linkedin.com, но у нас возникает следующий вопрос: как браузер подключается к linkedin.com? Каким образом два компьютера связываются друг с другом? Это соединение происходит по TCP, что расшифровывается как Transmission Control Protocol. Это сетевой протокол, используемый для установки соединения между двумя компьютерами в Интернете. TCP — это основной механизм доставки HTTP-запросов. Он передаёт информацию от одного компьютера другому при помощи пакетов. Это небольшой фрагмент данных, часть большего фрагмента данных; пакеты объединяются вместе, образуя передаваемый большой фрагмент данных.
Чтобы создать TCP-соединение, клиент должен инициировать подключение. Клиент делает это, отправляя пакет синхронизации (SYN), а сервер отвечает клиенту подтверждением синхронизации. Затем клиент отвечает серверу, подтверждая, что получил подтверждение синхронизации. Это называется подтверждением клиентом и сервером, а также трёхэтапным рукопожатием (three-way handshake).
После этого два компьютера подключены друг к другу по TCP, поэтому могут начать передавать HTTP-сообщения. Когда пользователь уходит с веб-сайта, соединение завершается. Для завершения этого TCP-соединения каждая из сторон отправляет другой стороне пакет завершения (fin), который другая сторона подтверждает. Это обозначает завершение соединения.
Hypertext Transfer Protocol (HTTP)
HTTP — это стандартный сетевой протокол, используемый для отправки запросов и ответов в вебе. HTTP-запросы в общем случае состоят из трёх компонентов:
- Строка запроса — включает в себя метод, путь и версию HTTP
- Заголовки — содержат пары «ключ-значение» дополнительной информации для сервера
- Тело — содержимое запроса, например, новые данные, загружаемые в POST-запросе.
Распространённые методы запросов :
- GET-запрос — это запрос серверу с просьбой отправки какой-то информации.
- POST-запрос используется, когда клиент отправляет информацию на сервер.
- PUT заменяет данные на сервере
- DELETE удаляет данные с сервера
- PATCH частично обновляет данные на сервере
- HEAD — это то же самое, что и GET, но без тела
- 200: OK (запрос выполнен)
- 201: создан (часто с POST-запросами)
- 301: перемещён навсегда (перенаправление)
- 302: обнаружен (перемещён временно)
- 400: плохой запрос
- 401: не авторизован (без аутентификации)
- 403: запрещён (у клиента отсутствует доступ к тому, что он пытается использовать)
- 404: не найден (указанный путь не содержит ресурса)
- 500: внутренняя ошибка сервера
- 503: сервис недоступен (если сервер отключён на запланированное обслуживание)
Hypertext Transfer Protocol Secure (HTTPS) — это расширение HTTP, используемое для безопасных онлайн-коммуникаций. Этот протокол требует, чтобы у серверов были доверенные сертификаты и чтобы они использовали Transport Layer Security (TLS) — протокол безопасности, надстроенный поверх TCP и предназначенный для шифрования данных, передаваемых между клиентом и сервером.
Перед передачей HTTP-сообщения по сети HTTPS оборачивает его в зашифрованные конверты. HTTPS скрывает тело сообщения и HTTP-заголовки, но не IP-адреса отправителя и получателя, показывающие, какие узлы общаются друг с другом.
Как браузеры рендерят контент
Что делает браузер с файлами HTML, получив их от сервера? Как он превращает этот HTML в страницу, с которой может взаимодействовать пользователь? Процесс получения файла HTML и его преобразования в пользовательский интерфейс называется критическими этапами рендеринга (critical rendering path). Всего существует пять критических этапов рендеринга:
- Парсинг HTML, создание дерева DOM и запросы всех найденных ресурсов (изображений, скриптов, шрифтов и таблиц стилей).
- Парсинг CSS в дерево CSS Object Model (CSSOM).
- Объединение DOM и CSSOM в дерево рендеринга, содержащее информацию об узлах, которые будут рендериться на странице.
- Вычисление структуры (ширины, высоты, местоположения) узлов на основании размера вьюпорта.
- Отрисовка экрана на основании дерева рендеринга и вычислений структуры.
▍ Динамические изменения
Что происходит, когда JavaScript пытается изменить какие-то элементы на странице? Мы можем разделить такие изменения на три типа:
- Изменение цвета : узел будет перерисован, это очень быстрая операция.
- Изменение позиции : повторный перерасчёт и перерисовка изменённого узла и одноуровневых узлов.
- Крупные изменения : повторный перерасчёт и перерисовка всей страницы.
▍ Оптимизация под критические этапы рендеринга
Что же мы можем сделать для оптимизации своего кода? Вот несколько идей:
- Использовать defer/async-скрипты — смысл заключается в том, чтобы скрипты не мешали рендерингу.
- Минимизировать размер DOM — чем глубже идёт наш код HTML, тем сложнее должно быть дерево DOM и тем дольше занимает парсинг такого HTML. Однако никогда не стоит жертвовать accessibility.
- Уменьшить размеры файлов при помощи сжатия/минификации.
- Использовать ленивую загрузку — определите, какой минимальный объём контента требуется вашей странице и не запрашивайте всё за раз. Когда страница становится интерактивной, начинайте запрашивать дополнительные ресурсы в фоновом режиме.
- Анимации с аппаратным ускорением — анимации сложны и способны сильно замедлить страницу. Если у вас есть замедляющая страницу анимация, то можно повысить её скорость рендеринга, добавив CSS-правило transform:translate 3D(0,0,0) . Это один из способов, которым можно сообщить браузеру, что необходимо использовать композитинг. При работе с трёхмерным пространством нам нужно выстраивать элементы послойно. Когда браузер выполняет это выстраивание, он понимает, насколько сложна анимация и применяет её аппаратное ускорение. Он будет обрабатывать её в GPU, а не в CPU, что обычно повышает производительность. Можно воспользоваться этим способом, если у вас есть проблемы со скоростью рендеринга анимаций.