OSEN-НИЙ SAAALEСкидка 50% на виртуальный хостинг и VDS
до 30.11.2025 Подробнее
Выберите продукт

HTTP 103 Early Hints на практике: включаем в Nginx и Apache и ускоряем загрузку ассетов

HTTP 103 Early Hints — способ подтолкнуть браузер к загрузке CSS/JS/шрифтов до 200 OK. В гайде — что реально ускоряется, как отобрать preload-цели, включить в Apache, пробросить через Nginx, сгенерировать 103 в приложении и безопасно проверить профит в метриках.
HTTP 103 Early Hints на практике: включаем в Nginx и Apache и ускоряем загрузку ассетов

HTTP 103 Early Hints — это промежуточный ответ сервера, который приходит до окончательного 200/304 и содержит подсказки в заголовках Link с rel=preload. Браузер, получив такой сигнал, может начать сетевые запросы за критичными ресурсами (CSS, JS, шрифты) раньше, чем увидит HTML-документ. На практике это уменьшает простой сети на критическом пути и ускоряет FCP/LCP, особенно на длинных TTFB и при холодных кэших.

Зачем нам early hints в 2025-м

Исторически для ранней доставки ресурсов пробовали HTTP/2 Server Push. Но push сложнее, легко ошибиться с кэшированием, он снят из браузеров Chromium и не считается устойчивой оптимизацией. Early hints, наоборот, сохраняет управление у браузера: сервер лишь подсказывает, а клиент решает — выгружать ресурс или нет. Это безопаснее с точки зрения перегрева канала и проще для эксплуатации.

Ключевая мысль: early hints — это «мягкое ускорение». Мы не насильно «толкаем» байты, а даём браузеру право начать загрузку, если он считает это уместным. Ошибиться труднее, откат — банально убрать лишние Link.

Как работает 103 Early Hints (вкратце)

Последовательность выглядит так:

  1. Клиент отправляет запрос страницы.
  2. Сервер как можно раньше шлёт промежуточный ответ HTTP/2 103 или HTTP/1.1 103 и один или несколько заголовков Link с rel=preload.
  3. Браузер начинает грузить эти ресурсы параллельно подготовке основного ответа.
  4. Приходит финальный ответ (обычно 200 OK), страница продолжает рендер.

Поддержка у современных браузеров есть в Chromium-семействе и Safari; Firefox экспериментировал и может требовать флагов. Даже если конкретный клиент проигнорирует 103, финальные Link: preload в ответе 200 не мешают — они просто не дадут выигрыш настолько рано.

Схема: 103 Early Hints приходят до финального 200 OK

Какие ассеты реально стоит preload-ить

Ресурсы в 103 должны быть «на 100% понадобятся» сразу после старта рендеринга:

  • Критический CSS основного бандла: as=style.
  • Ключевой JS, без которого не работает above-the-fold: as=script.
  • Первичный webfont для заголовков/основного текста: as=font; type=font/woff2; crossorigin.

Аккуратно с картинками: они огромные и часто лениво подгружаются. Если у вас стабильный hero на первом экране, preload может помочь, но проверяйте метрики — иногда лучше fetchpriority=high в HTML.

Золотое правило: не более 3–6 ссылок в 103. Чем больше подсказок, тем выше шанс лишней конкуренции за TCP-оконце и рост блокировок при медленном канале.

Apache: включаем early hints за 5 минут

Apache умеет генерировать 103 на уровне веб-сервера. Вам понадобится mod_http2 и mod_headers. Проверьте, что HTTP/2 включён для виртуального хоста, и добавьте подсказки с атрибутом early.

# httpd.conf (или в конфиге vhost)
LoadModule http2_module modules/mod_http2.so
LoadModule headers_module modules/mod_headers.so

# Внутри виртуального хоста TLS
<VirtualHost *:443>
  ServerName example.com
  Protocols h2 http/1.1

  # Включаем генерацию 103
  H2EarlyHints On

  # Список preload через Link, именно для 103
  Header add Link "</assets/app.css>; rel=preload; as=style" early
  Header add Link "</assets/app.js>; rel=preload; as=script" early
  Header add Link "</fonts/Inter.woff2>; rel=preload; as=font; type=font/woff2; crossorigin" early

  DocumentRoot "/var/www/html"
</VirtualHost>

Пара замечаний:

  • early говорит mod_headers положить заголовок именно в 103, а не только в финальный ответ.
  • Если у вас динамика по ассетам (хеш в имени файла), поддерживайте шаблоны через переменные окружения/перегенерацию конфига при деплое.
  • Присваивайте корректный as и type — браузер использует их для планирования.

Если параллельно настраиваете безопасность, пригодится наш разбор про заголовки: HTTP Security Headers в Nginx и Apache.

Сгенерировать 103 из приложения за Apache

Apache также способен пробросить 103, если его сгенерировало приложение до финального ответа. Это полезно, когда список ассетов зависит от рендеринга.

# PHP (apache2handler). Работает только если фронтенд допускает 103
header('HTTP/1.1 103 Early Hints');
header('Link: </assets/app.css>; rel=preload; as=style', false);
header('Link: </assets/app.js>; rel=preload; as=script', false);
flush();

// Далее обычная отдача HTML
http_response_code(200);
echo '<!doctype html>...';

В php-fpm за прокси поведение зависит от фронтенда: не каждый сервер пробрасывает 103 дальше. Смотрите следующий раздел для Nginx.

Фрагмент конфигурации Apache с H2EarlyHints и Link early

Nginx и 103: реалистичные варианты

В чистом Nginx нет штатной директивы, которая «синтезирует» 103 из Link-списка, как это делает Apache. Практически применимы два пути:

  1. Приложение само отправляет 103 (Node.js, Go, некоторые фреймворки на Ruby/Java), а Nginx пробрасывает ответ клиенту.
  2. Nginx проксирует на Apache, который формирует 103, а Nginx выполняет роль фронтенда/балансера.

В обоих случаях важно протестировать, что конкретная версия Nginx в вашем окружении действительно пересылает промежуточные ответы 1xx клиенту. Клиентская сторона должна говорить по HTTP/2 или HTTP/3, иначе выгоды не будет.

# Пример reverse proxy Nginx перед Apache или приложением, которое шлёт 103
server {
  listen 443 ssl http2;
  server_name example.com;

  # TLS-настройки опущены

  location / {
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto https;
    proxy_pass http://127.0.0.1:8080;
  }
}

Если у вас проект на собственном сервере, удобнее всего экспериментировать на VDS: полный доступ к конфигам Nginx/Apache и логам. Для HTTPS сразу подключайте SSL-сертификаты, иначе браузеры не включат HTTP/2/3 и профит от 103 будет минимальным. Для сравнения стеков и подходов также посмотрите материал Nginx vs Apache в 2025.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Генерация 103 на уровне приложения (через Nginx)

Современные рантаймы позволяют отправлять 103 самостоятельно. Два рабочих примера:

// Node.js (18+) — Express-подобный обработчик
res.writeEarlyHints({
  Link: '</assets/app.css>; rel=preload; as=style, </assets/app.js>; rel=preload; as=script'
});
res.status(200).send('<!doctype html>...');
// Go (1.19+) — net/http
w.Header().Add("Link", "</assets/app.css>; rel=preload; as=style")
w.Header().Add("Link", "</assets/app.js>; rel=preload; as=script")
w.WriteHeader(103)
if f, ok := w.(http.Flusher); ok { f.Flush() }

// финальный ответ
w.WriteHeader(200)
w.Write([]byte("<!doctype html>..."))

Проверка: видит ли клиент 103

Самый простой способ — через curl и сетевой инспектор браузера.

# Сырой заголовочный обмен с HTTP/2
curl -I --http2 --raw https://example.com/

В корректной реализации вы увидите два блока статуса: сначала HTTP/2 103 с несколькими Link, затем финальный HTTP/2 200. В DevTools в разделе Network откройте запрос документа: Chrome показывает секцию «103 Early Hints» с теми же заголовками.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Как подбирать список Link: preload

Алгоритм, который хорошо себя показал в продакшене:

  1. Соберите критический путь от навигации до первого значимого рендера (FCP/LCP). Обычно это главный CSS и один-два JS-чанка.
  2. Проверьте кэшируемость: 103 особенно полезен при холодном кэше и на первой загрузке.
  3. Добавьте webfont только если он используется на первом экране и без него будет layout shift. Не забудьте crossorigin.
  4. Не preload-ьте ресурсы, которые могут не понадобиться на этой странице (динамические виджеты ниже фолда).
  5. Ограничьте объём: суммарный размер preload-ресурсов не должен забивать канал и мешать получению HTML.

В помощь с кэшированием статики — чеклист и примеры в статье Cache-Control и ETag для статики. Для кросс-доменных шрифтов/ассетов может пригодиться настройка CORS: CORS-заголовки в Nginx и Apache.

Метрики: что измерять и как интерпретировать

Целевые индикаторы при включении early hints:

  • Снижение FCP/LCP на медленных сетях и при высоком TTFB.
  • Уменьшение времени загрузки первого CSS-файла и главного JS-бандла.
  • Стабилизация рендеринга: меньше layout shift из-за шрифтов (если preload фонтов корректен).

Проводите A/B: часть трафика без 103, часть — с 103, одинаковые списки Link в 200. Ищите статистически значимое улучшение. Если дельта незаметна — возможно, у вас и так быстрый TTFB или ассеты уже в кэше.

Частые ошибки и подводные камни

  • Отсутствует as или указан неверно. Браузер может проигнорировать preload или ошибиться с приоритетами.
  • Шрифты без crossorigin. Для фонтов через Link: preload требуется crossorigin, иначе запрос пойдёт дважды.
  • Предзагрузка тяжёлых изображений, которые не участвуют в LCP. Это расходует бюджет канала, замедляя доставку HTML.
  • Дублирующиеся preload в 103 и в HTML. Само по себе не критично, но поддерживать сложнее; держите источник истины один.
  • Слишком много ссылок в 103. Ограничьте до самого необходимого.

Rollback и фичефлаг

Делайте включение 103 управляемым: флаг в конфиге Apache (H2EarlyHints On|Off) или переключатель на уровне приложения. В случае деградации сети/клиентов достаточно убрать секцию с Link early или перестать эмитить 103 из кода. Финальные Link на 200 можно оставить — они не навредят.

Чем early hints отличаются от HTTP/2 Push

Коротко: push пытался предугадать и «запихнуть» ресурс в клиент, часто мимо кэша и приоритетов, что приводило к избыточному трафику; браузеры его убрали. Early hints лишь подсказывают, какие запросы стоит начать раньше, на условиях клиента. Это делает оптимизацию предсказуемой, простой и совместимой с кэшем.

Итоги

HTTP 103 Early Hints — практичный способ ускорить загрузку критичных ассетов без тяжёлой инфраструктуры. Apache позволяет включить 103 буквально несколькими строками, а для Nginx рабочая стратегия — пробрасывать 103, сформированный приложением или бэкендом на Apache. Дисциплина в выборе ресурсов для preload и аккуратные эксперименты с метриками дадут ощутимый выигрыш в реальном UX без риска перегреть канал и усложнить поддержку.

Поделиться статьей

Вам будет интересно

DMARC: rua, p=quarantine и p=reject — как включить без потери доставляемости OpenAI Статья написана AI (GPT 5)

DMARC: rua, p=quarantine и p=reject — как включить без потери доставляемости

Пошаговое руководство для админов: что такое DMARC и агрегированные отчёты rua, как правильно оформить rua=mailto, собрать XML-отч ...
Floating IP для Nginx: keepalived VRRP, healthcheck и быстрый failover OpenAI Статья написана AI (GPT 5)

Floating IP для Nginx: keepalived VRRP, healthcheck и быстрый failover

Пошагово строим отказоустойчивый фронтенд на двух серверах Nginx с общим floating IP. Настраиваем keepalived (VRRP), HTTP health c ...
SYNPROXY в nftables: защита VDS от TCP SYN flood пошагово OpenAI Статья написана AI (GPT 5)

SYNPROXY в nftables: защита VDS от TCP SYN flood пошагово

SYN flood забивает TCP-очереди и conntrack на VDS, съедая CPU. SYNPROXY в nftables отсекает мусор до TCP-стека. Разбираем принцип, ...