Этап 1 — Браузер: что происходит до отправки пакета

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

1. Архитектура браузера: кто делает запрос

Современный браузер — не одна программа, а оркестр процессов. Когда ты вводишь URL и жмёшь Enter, в работу включаются как минимум три:

ПроцессЧто делает
Browser process (главный)UI, адресная строка, вкладки, история. Решает «открыть URL — какой процесс этим займётся?»
Renderer process (по одному на сайт)Парсит HTML/CSS/JS, выполняет JS, рисует страницу. Изолирован — упал сайт, остальные живы.
Network process (один на браузер)Делает реальные сетевые запросы. Управляет соединениями, кэшем, куками. Через него идут запросы ВСЕХ вкладок.
GPU processРисует пиксели на экране.
Utility processesСервис-воркеры, расширения, аудио, видео.

Эта изоляция (sandbox) — фундамент безопасности современных браузеров. Один сайт не может прочитать память другого, и атака на JS не вылезает наружу процесса.

Аналогия

Браузер = бизнес-центр с разными отделами

Browser process — это ресепшен: ты приходишь сюда, говоришь «хочу попасть в офис №42», и тебя направляют. Network process — это служба доставки, она ходит наружу за заказами. Renderer process — отдельный офис каждого арендатора, в котором делается реальная работа. Никто не лезет в чужой офис.

2. Парсинг URL — спецификация WHATWG

Когда ты ввёл app.example.com/login?next=/dashboard, браузер должен это разобрать. Это сложнее, чем кажется — есть целая спецификация WHATWG URL.

Шаг 1: дополнение схемы

Если ты не написал https://, браузер сам это добавит. Логика:

Шаг 2: разбор по компонентам

# Берём URL:
https://alice:s3cr3t@api.example.com:8443/v2/users/42?tab=info&ref=email#section-2

scheme   # https
userinfo # alice:s3cr3t  (раритет, опасен)
host     # api.example.com
port     # 8443
path     # /v2/users/42
query    # tab=info&ref=email
fragment # section-2 (не уходит на сервер!)

Шаг 3: нормализация

Браузер приводит URL к каноническому виду:

Шаг 4: IDN и Punycode

Если в имени домена есть не-ASCII (например пример.рф или café.com), браузер преобразует его в Punycode:

café.com    →   xn--caf-dma.com
яндекс.рф   →   xn--d1acpjx3f.xn--p1ai

Это нужно, потому что DNS не понимает Unicode напрямую. Punycode — это «безопасный» ASCII-аналог любого Unicode-имени.

⚠️ Homograph-атака

Кириллическое «а» (U+0430) внешне неотличимо от латинского «a» (U+0061). Атакующий регистрирует аpple.com (с кириллической «а»), и пользователь не отличит от apple.com. Браузеры это знают и в подозрительных случаях показывают URL в Punycode (xn--pple-43d.com). Это твоя первая встреча с browser security.

3. Проверка локального HTTP-кэша

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

Кэшированный ответ имеет заголовки, которые сервер прислал в прошлый раз:

HTTP/2 200 OK
Cache-Control: public, max-age=300, immutable
ETag: "v2-7c8f3a"
Last-Modified: Wed, 15 May 2026 11:00:00 GMT
Date: Wed, 15 May 2026 11:55:00 GMT
Content-Type: text/html

Логика браузера:

  1. Свежий? Если (now - Date) < max-age и нет no-cache — отдаём из кэша моментально. Никакого сетевого запроса.
  2. Просрочен, но есть ETag? Делаем условный запрос: GET / HTTP/2 If-None-Match: "v2-7c8f3a". Сервер сравнит и ответит либо 304 Not Modified (используй кэш), либо новый 200 с новой версией.
  3. no-store? Кэш игнорируется, всегда новый запрос.
  4. Кэша вообще нет? Делаем обычный запрос.

Это огромная экономия трафика. Большой сайт может отдавать 80% запросов из браузерного кэша.

4. Иерархия кэшей

Слово «кэш» в браузере — это на самом деле несколько кэшей:

КэшГдеСрок жизни
Memory cacheВ оперативке renderer-процессаДо закрытия вкладки
Disk cacheНа дискеДо явного очищения / нехватки места
Service Worker cacheAPI CacheStorage, управляется JSКак настроит разработчик (даже offline)
Push cacheHTTP/2 server push (устарело)Жизнь HTTP/2-соединения
Prefetch cacheЗаранее загруженные ресурсы~5 минут

Когда ты делаешь fetch — браузер по цепочке смотрит во все эти кэши. Service Worker (если зарегистрирован сайтом) имеет приоритет — он может вообще перехватить запрос и ответить «из своего кэша», не идя в сеть. Так работают PWA.

5. Fetch — единый API запросов

В современных браузерах ВСЕ исходящие запросы — будь то «открыть страницу», img src=, fetch() из JS, AJAX, iframe — проходят через Fetch Standard. Это набор шагов:

  1. CORS check. Запрос идёт на тот же origin (схема+хост+порт)? Тогда всё разрешено. Иначе — проверка CORS, возможно preflight.
  2. Service Worker intercept. Если зарегистрирован SW и его scope покрывает URL — ему даётся возможность перехватить.
  3. HTTP cache lookup. Описано выше.
  4. Content Security Policy. Если сайт прислал заголовок CSP, проверяется, разрешён ли этот URL для этого типа ресурса.
  5. Permissions Policy. Можно ли вообще этому контексту делать такие запросы.
  6. Network — если ничего не остановило, идём в Network process.

6. Preconnect, preload, prefetch — гонка за миллисекунды

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

В HTML это указывается так:

<link rel="dns-prefetch" href="//fonts.googleapis.com">
<link rel="preconnect" href="https://api.example.com">
<link rel="preload"      as="font" href="/Inter.woff2" crossorigin>
<link rel="prefetch"     href="/dashboard">
ПодсказкаЧто делаетКогда применять
dns-prefetchРезолвит DNS заранееЗнаешь, что скоро понадобится этот домен (баннер, аналитика)
preconnectDNS + TCP + TLS-handshakeНа критичный домен — экономит ~100-200мс
preloadСразу качает ресурсШрифты, ключевые JS — то, без чего страница не работает
prefetchКачает в фон с низким приоритетомСледующая вероятная страница
modulepreloadpreload, но для JS-модулейСовременные ES-модули
DevOps-задача

Если у тебя сайт критичен к производительности, в шаблон HTML добавляешь preconnect на все домены, с которых придут шрифты, картинки, аналитика. Эффект — Largest Contentful Paint улучшается на 50-200 мс. Это просто, бесплатно, и почему-то 80% сайтов этим пренебрегают.

7. 103 Early Hints — что нового в HTTP

HTTP-статус 103 Early Hints — относительно новая возможность. Сервер может прислать сначала «предварительный» ответ со списком ресурсов, которые точно понадобятся для страницы, ещё до того, как сама страница готова.

# Сервер начинает обрабатывать запрос…
# …и сразу шлёт промежуточный ответ:
HTTP/2 103 Early Hints
Link: </css/critical.css>; rel=preload; as=style
Link: </fonts/Inter.woff2>; rel=preload; as=font; crossorigin

# Браузер начинает качать эти ресурсы, пока сервер ещё думает.
# Когда сервер закончит — пришлёт обычный 200 OK с HTML.
HTTP/2 200 OK
Content-Type: text/html

<!DOCTYPE html>…

Это позволяет «склеить» подготовку страницы и загрузку её ресурсов параллельно. Cloudflare и Fastly поддерживают, AWS CloudFront — в beta. Запомни и предлагай на собеседовании, если речь о performance.

8. Connection reuse — почему второй запрос быстрее

Открыл сайт. Браузер установил TCP+TLS соединение — занимает 100-300мс. А потом этот же сайт делает запрос к API на том же домене. Что происходит?

Браузер переиспользует уже открытое соединение. Никакого нового TCP/TLS — просто отправляет следующий запрос. Это называется HTTP keep-alive (в HTTP/1.1) или multiplexing (в HTTP/2 и /3).

Сколько соединений браузер держит к одному домену?

Поэтому когда сайт переходит с HTTP/1.1 на HTTP/2, скорость может вырасти кратно — особенно при множестве мелких ресурсов.

9. Connection coalescing — секретная оптимизация

А что, если у тебя на сайте подключены ресурсы с разных поддоменов одного хоста — www.example.com, api.example.com, cdn.example.com? По логике нужно три соединения.

Но если все три указывают через DNS на одни и те же IP, и у них один сертификат с Subject Alternative Names, покрывающий все три имени, — браузер использует одно HTTP/2-соединение для всех трёх. Это и есть connection coalescing.

В цифрах: сайт-«монстр» с 20 поддоменами на одной инфраструктуре в HTTP/2 откроет 1-2 соединения вместо 20. Экономит 1-2 секунды на первой загрузке.

10. Referrer и куки — что улетает наружу

Прежде чем браузер отправит запрос, он подкладывает:

GET /v2/users/42 HTTP/2
Host: api.example.com
Referer: https://app.example.com/dashboard       # откуда я пришёл
Origin: https://app.example.com                 # origin страницы (без пути)
User-Agent: Mozilla/5.0 ...
Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
Sec-Ch-Ua: "Chrome";v="120", ...
Cookie: session=abc; csrf=xyz                # куки для этого хоста

Какие куки попадают в запрос

Браузер просматривает cookie jar и берёт куки, у которых:

Referrer Policy

Заголовок Referer может раскрывать чувствительную информацию (например, путь с токеном). Сайты управляют через Referrer-Policy:

Referrer-Policy: strict-origin-when-cross-origin  # умолчание сейчас
# Шлёт полный URL — на тот же origin. Только origin — на чужие HTTPS. Ничего — на HTTP.

11. CORS — почему запрос вообще может отказаться уйти

Кросс-доменные запросы (когда страница с одного origin делает запрос к другому) — это особый случай. Без специального разрешения сервера браузер их не отправит. Это Same-Origin Policy — фундамент веб-безопасности с 90-х.

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

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true

Для «небезопасных» запросов (PUT, DELETE, не-простые заголовки) браузер сначала шлёт preflightOPTIONS-запрос, который спрашивает: «можно ли мне сделать такой запрос?». Если ответ ok — браузер шлёт настоящий запрос.

DevOps-боль

«CORS error» — самая частая жалоба разработчиков фронтенда. И всегда — это сервер что-то не так настроил, а не браузер «неправильно работает». Чините на стороне ответов сервера: правильные Access-Control-Allow-Origin, корректная обработка OPTIONS, правильные Vary-заголовки.

12. CSP — Content Security Policy

Сайт может прислать заголовок CSP, говорящий браузеру: «загружай ресурсы только с этих источников, остальные блокируй». Это защита от XSS — даже если злоумышленник внедрил скрипт через дыру в HTML, браузер откажется его исполнить.

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  img-src 'self' data: https:;
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';

Это твоя обязательная гигиена как DevSecOps. Сайт без CSP в 2026 году — это плохо.

13. Просмотреть всё это в DevTools

Открой Chrome / Firefox DevTools (F12) → вкладка Network. Сделай запрос. Вкладка Timing у каждого ресурса покажет:

Queued at:           0 ms       # когда фетч встал в очередь
Started at:          12 ms      # когда реально начался
Stalled:             4 ms       # ожидание свободного соединения
DNS Lookup:          18 ms      # резолвинг (если кэша не было)
Initial connection:  40 ms      # TCP handshake
SSL:                 35 ms      # TLS handshake
Request sent:        0.3 ms     # отправка запроса
Waiting (TTFB):      150 ms     # ожидание ответа сервера
Content Download:    25 ms      # скачивание тела

Каждая из этих секунд — отдельный этап в этом deep dive. Через 9 уроков ты будешь читать эту таблицу как родную.

14. Команды и упражнения

Через curl увидеть тот же запрос

# Показать всё, что curl шлёт и получает
curl -v --http2 https://example.com

# Эмулировать поведение браузера — нужный User-Agent, follow redirects
curl -v -L \
  -H "User-Agent: Mozilla/5.0" \
  -H "Accept: text/html,application/xhtml+xml,*/*;q=0.8" \
  https://example.com

# Получить разбивку времени по фазам
curl -o /dev/null -s -w \
  "DNS: %{time_namelookup}s
Connect: %{time_connect}s
TLS: %{time_appconnect}s
TTFB: %{time_starttransfer}s
Total: %{time_total}s
" https://example.com

Посмотреть свой HTTP-кэш

Chrome: chrome://net-internals/#httpCache — список всех закэшированных ответов. Можно изучить.

Тестировать preconnect

# Открой DevTools → Performance → Record
# Загрузи страницу один раз с preconnect, второй — без.
# Сравни LCP (Largest Contentful Paint).

15. Что с этим делает DevOps

Чек-лист «понимаю это»

Прежде чем пакет уйдёт в сеть, браузер: (1) парсит URL по WHATWG, (2) ищет ответ в иерархии кэшей, (3) проходит CORS/CSP-проверки, (4) переиспользует или открывает соединение, (5) подкладывает куки и заголовки. На этом этапе DevOps управляет: Cache-Control, HSTS, CSP, CORS, preconnect-подсказки.