Preload, prefetch, preconnect и 103 Early Hints: прогрев загрузки
Браузер открывает страницу не как единый документ, а как последовательность сотен решений: какой ресурс запросить первым, какое соединение установить заранее, какой шрифт подождать, а какую картинку отложить. Если оставить эти решения целиком на усмотрение браузера, на сложном сайте легко потерять 300–800 мс на критическом пути — и это напрямую бьёт по скорости отрисовки главного контента и месте в выдаче. Resource hints и протокол 103 Early Hints — это инструменты «прогрева» загрузки: вы заранее говорите браузеру, что и в каком порядке готовить. В этой статье разберём preload, preconnect, dns-prefetch, prefetch и modulepreload, объясним, как работает HTTP 103, что такое fetchpriority, как это влияет на LCP и INP, и почему перегрев хинтами вредит не меньше, чем их отсутствие.
Что такое resource hints и зачем они нужны
Resource hints — это директивы, которые сообщают браузеру о ресурсах и соединениях, нужных странице, до того как он сам обнаружит их в ходе разбора HTML. По умолчанию браузер находит ресурсы постепенно: парсит HTML, встречает ссылку на CSS, запрашивает его, парсит CSS, находит шрифт, запрашивает шрифт. Эта цепочка обнаружения добавляет задержки на каждом шаге, особенно если ресурсы живут на сторонних доменах, к которым ещё нужно установить соединение. Хинты разрывают цепочку: вы вручную выносите критичные запросы вперёд.
Все хинты задаются тегом <link> в секции <head> или через HTTP-заголовок Link. Атрибут rel определяет тип хинта: preload, preconnect, dns-prefetch, prefetch, modulepreload. Принципиально важно понимать разницу между двумя классами хинтов. Одни (preconnect, dns-prefetch) греют соединение — заранее проводят DNS-резолвинг и TCP/TLS-рукопожатие. Другие (preload, prefetch, modulepreload) греют сам ресурс — инициируют его загрузку до момента естественного обнаружения.
Ошибка номер один в реальных проектах — относиться к хинтам как к «волшебной таблетке ускорения» и навешивать их на всё подряд. Хинты не создают пропускную способность из воздуха: канал и количество одновременных соединений конечны. Каждый ресурс, который вы прогреваете без надобности, забирает полосу у того, что действительно нужно для первого экрана. Поэтому грамотный аудит начинается не с добавления хинтов, а с понимания критического пути рендеринга — что именно блокирует первую отрисовку и LCP-элемент.
Resource hints — это не педаль газа, а раскладка инструментов перед операцией: вы заранее достаёте только то, что точно понадобится, и в нужном порядке. Лишний инструмент на столе мешает, а не помогает.
Preconnect и dns-prefetch: прогрев соединений
Прежде чем браузер скачает хоть один байт со стороннего домена, он должен пройти три этапа: DNS-резолвинг (превращение имени домена в IP-адрес), TCP-рукопожатие и, для HTTPS, TLS-рукопожатие. На мобильной сети с высокой задержкой каждое из этих рукопожатий стоит 100–300 мс, а в сумме холодное подключение к новому домену легко съедает 300–600 мс. Если ваш LCP-элемент — это изображение героя с CDN, а соединение с этим CDN устанавливается только в момент обнаружения картинки, вы теряете эти миллисекунды прямо в критическом пути.
preconnect заранее проходит все три этапа: <link rel="preconnect" href="https://cdn.example.com" crossorigin>. К моменту, когда браузер обнаружит ресурс на этом домене, соединение уже готово, и запрос уходит мгновенно. Атрибут crossorigin обязателен для ресурсов, загружаемых в анонимном режиме (шрифты, fetch, модули) — без него браузер откроет отдельное соединение и прогрев пропадёт впустую. Это классическая скрытая ошибка: preconnect к домену шрифтов без crossorigin фактически не работает для самих шрифтов.
dns-prefetch — это облегчённая версия preconnect, которая выполняет только DNS-резолвинг. Он дешевле по ресурсам и поддерживается шире, поэтому его часто ставят как запасной вариант вместе с preconnect для одного домена. На практике связка выглядит так: preconnect для 2–4 критичных сторонних доменов (CDN изображений, домен шрифтов, аналитика, платёжный виджет на первом экране) и dns-prefetch для менее важных. Держать preconnect больше чем к 4–6 доменам не стоит — каждое открытое соединение потребляет память и конкурирует за полосу. Эти приёмы тесно связаны с общей оптимизацией сервера и хостинга и временем ответа сервера TTFB до 200 мс.
Preload: загрузка критичных ресурсов вперёд
preload — самый мощный и самый опасный хинт. Он говорит браузеру: «Этот ресурс точно понадобится для текущей страницы, начни грузить его прямо сейчас с высоким приоритетом». В отличие от preconnect, который только готовит соединение, preload инициирует фактическую загрузку. Используется он для ресурсов, которые браузер обнаруживает поздно, но которые критичны для рендеринга: шрифты, спрятанные внутри CSS, LCP-изображение, заданное через CSS-фон, критичные скрипты, подгружаемые динамически.
Синтаксис требует обязательного атрибута as, который указывает тип ресурса: <link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>. Без правильного as браузер не сможет назначить корректный приоритет и применить нужную политику CORS, а в части случаев загрузит ресурс дважды. Для шрифтов crossorigin обязателен всегда, даже если шрифт лежит на вашем же домене — потому что шрифты всегда грузятся в анонимном режиме. Это вторая по частоте ошибка после отсутствия crossorigin в preconnect.
Самый ценный сценарий preload — это прогрев LCP-изображения. Если главный визуальный элемент страницы задаётся не тегом img в начале HTML, а через CSS background-image или вставляется JavaScript-ом, браузер обнаружит его очень поздно. Preload с атрибутом fetchpriority="high" позволяет начать загрузку немедленно. По нашим замерам на сайтах с тяжёлым героем это сокращает LCP на 0,4–1,2 секунды — разница между «красной» и «зелёной» зоной Core Web Vitals.
Но именно с preload связан главный риск перегрева. Если вы прелоадите ресурс, который на самом деле не используется на странице (например, шрифт, который применяется только в одном редком блоке, или картинку, которую браузер и так нашёл бы быстро), вы отнимаете полосу у действительно критичных запросов и замедляете LCP вместо ускорения. Консоль браузера честно предупреждает: «The resource was preloaded but not used within a few seconds» — это сигнал убрать лишний хинт.
Prefetch и modulepreload: будущее и модули
prefetch принципиально отличается от preload по семантике времени. Preload — это «нужно сейчас, для текущей страницы». Prefetch — это «вероятно понадобится потом, на следующей странице». Браузер загружает prefetch-ресурсы с самым низким приоритетом, в простое, не мешая текущей загрузке, и складывает их в кэш. Классический сценарий — предзагрузка JS-бандла или данных следующей страницы, на которую пользователь с высокой вероятностью перейдёт: товар из листинга, следующий шаг воронки, вторая страница пагинации.
Использовать prefetch нужно осторожно: вы тратите трафик пользователя на ресурс, который может и не понадобиться. На мобильных тарифах с лимитом это плохой тон. Хорошая практика — прогревать только сценарии с действительно высокой вероятностью перехода и учитывать Save-Data заголовок. Многие современные фреймворки делают это автоматически: ссылки в зоне видимости получают prefetch, остальные — нет.
modulepreload — это специализированный preload для ES-модулей. Когда сайт использует нативные ES-модули (<script type="module">), браузер обнаруживает граф зависимостей постепенно: грузит точку входа, парсит, находит импорты, грузит их, парсит, находит их импорты. Это водопад запросов. modulepreload позволяет прогреть весь граф сразу, объявив все нужные модули в head. Он не только загружает модуль, но и парсит его и помещает в граф модулей, готовый к исполнению. Для приложений на JavaScript-фреймворках и SPA это особенно важно.
| Хинт | Что делает | Приоритет | Типичное применение |
|---|---|---|---|
| dns-prefetch | Только DNS-резолвинг | Низкий | Запасной вариант, неприоритетные домены |
| preconnect | DNS + TCP + TLS | Высокий | CDN, шрифты, критичные сторонние домены |
| preload | Загрузка ресурса сейчас | Высокий | Шрифты, LCP-картинка, поздно обнаруживаемые ресурсы |
| modulepreload | Загрузка + парсинг ES-модуля | Высокий | Граф модулей в SPA |
| prefetch | Загрузка для будущей навигации | Самый низкий | Ресурсы следующей страницы |
HTTP 103 Early Hints: прогрев до ответа сервера
Все хинты в head имеют общее ограничение: браузер увидит их только после того, как сервер пришлёт начало HTML-документа. А если сервер думает над ответом 300–500 мс (запросы к базе, рендеринг шаблона, обращение к API), всё это время браузер простаивает, не зная даже, какие соединения готовить. HTTP 103 Early Hints решает именно эту проблему. Это промежуточный информационный ответ, который сервер отправляет до основного ответа 200, пока ещё готовит контент.
Механика такая: пользователь запросил страницу, сервер сразу же, не дожидаясь готовности HTML, отправляет ответ 103 Early Hints с заголовками Link, содержащими preload и preconnect для критичных ресурсов. Браузер начинает прогрев соединений и загрузку шрифтов и CSS прямо в тот момент, пока бэкенд ещё формирует тело страницы. Когда приходит финальный ответ 200, часть критичных ресурсов уже в кэше или соединения уже открыты. На сайтах с высоким временем серверной обработки выигрыш достигает 200–400 мс на LCP.
Поддержка 103 уже есть в Chrome, Cloudflare, Fastly и ряде серверов; реализуется обычно на уровне CDN или реверс-прокси. Важно: 103 имеет смысл только тогда, когда серверная обработка занимает заметное время. Если TTFB и так минимальный, выигрыша почти не будет, а на статике через CDN с эффективной отдачей эффект сводится к нулю. Перед внедрением убедитесь, что у вас действительно есть «окно ожидания», которое можно занять полезной работой.
Приоритеты ресурсов и атрибут fetchpriority
Браузер сам назначает каждому запросу внутренний приоритет: CSS из head — высокий, шрифты — высокий, картинки в области видимости — низкий до момента вёрстки, скрипты — в зависимости от async/defer. Этот алгоритм работает хорошо в среднем случае, но не знает специфики вашей страницы. Атрибут fetchpriority со значениями high, low и auto позволяет вмешаться в приоритезацию там, где браузер ошибается.
Главный сценарий — LCP-изображение. По умолчанию браузер назначает картинкам низкий приоритет, пока не выполнит вёрстку и не поймёт, какие из них видимы. Но LCP-картинку видно сразу, и ждать вёрстки не нужно. Поставив <img src="hero.webp" fetchpriority="high">, вы сообщаете браузеру приоритет немедленно, без preload и без лишних тегов в head. Это самый чистый способ ускорить LCP для картинок, присутствующих в исходном HTML.
Обратная сторона — понижение приоритета. Скрипты аналитики, виджеты чатов, баннеры третьего экрана можно пометить fetchpriority="low" или загружать с defer, чтобы они не конкурировали за полосу с критичным контентом. Грамотная работа с приоритетами — это игра с нулевой суммой: ускоряя одно, вы замедляете другое, поэтому повышать приоритет нужно только тому, что действительно на критическом пути. Эта логика прямо связана с управлением критическим CSS и render-blocking ресурсами.
Влияние на LCP и INP: где хинты реально работают
На метрику LCP хинты влияют наиболее прямо. LCP — это момент отрисовки самого крупного элемента первого экрана, и почти всегда это либо текстовый блок, зависящий от шрифта и CSS, либо изображение. Прогрев соединения к CDN изображений, preload LCP-картинки и fetchpriority high сокращают «время до пикселя» именно для этого элемента. На текстовых LCP помогает preload критичного шрифта в связке с правильным font-display и оптимизацией шрифтов, чтобы текст не висел невидимым в ожидании веб-шрифта.
С INP связь тоньше, но она есть. INP измеряет отзывчивость интерфейса на действия пользователя, и зависит она в основном от загрузки и работы JavaScript. Хинты влияют косвенно: если вы прогреваете критичные ресурсы и не перегружаете канал, главный поток быстрее освобождается, обработчики событий навешиваются раньше, и взаимодействия обрабатываются без задержек. А вот перегрев хинтами вредит INP напрямую — лавина одновременных загрузок и парсинг прелоаженных, но не нужных модулей нагружают главный поток и удлиняют задержку отклика. Подробнее о метрике — в материале про INP как новый Core Web Vital.
Важно измерять эффект, а не верить теории. Используйте панель Network в DevTools с включённой колонкой Priority, лабораторные прогоны в Lighthouse и, главное, полевые данные из Google Search Console и отчёта Core Web Vitals. Любой хинт оценивается по принципу «было/стало»: добавили preload — замерили LCP до и после на реальных устройствах. Если улучшения нет или метрика ухудшилась, хинт убирается.
Что и когда греть: пошаговый алгоритм
Чтобы не превращать прогрев в хаос, мы используем строгий порядок действий. Сначала анализируется критический путь, затем точечно добавляются хинты под конкретные узкие места, и только после этого проверяется результат. Никаких хинтов «на всякий случай».
- Найдите LCP-элемент. Откройте Lighthouse или DevTools и определите, что именно является крупнейшей отрисовкой — картинка, заголовок, блок текста.
- Определите сторонние домены на критическом пути. CDN картинок, домен шрифтов, критичный сторонний скрипт — кандидаты на preconnect.
- Прогрейте соединения. Добавьте preconnect (с crossorigin где нужно) к 2–4 важнейшим доменам, dns-prefetch для остальных.
- Прелоадите поздно обнаруживаемые ресурсы. Критичный шрифт, LCP-картинку из CSS-фона, критичный динамический скрипт.
- Расставьте приоритеты. fetchpriority high — LCP-картинке, low — некритичным виджетам и аналитике.
- Включите 103 Early Hints, если велик TTFB. Вынесите preconnect и preload в заголовок 103.
- Замерьте и почистите. Уберите хинты, дающие предупреждения «preloaded but not used» или не улучшающие метрики.
Этот алгоритм встраивается в любую серьёзную оптимизацию сайта на WordPress и других CMS. На WordPress часть хинтов добавляют кэширующие плагины автоматически, но они склонны к перегреву — обязательно проверяйте, что прелоадится, и убирайте лишнее вручную.
Типичные ошибки прогрева загрузки
За годы аудитов мы видим один и тот же набор ошибок, который из инструмента ускорения делает инструмент замедления. Собрали их в чеклист — пройдитесь по нему перед публикацией.
- Preload без crossorigin для шрифтов. Шрифт грузится дважды или прогрев не срабатывает. crossorigin для шрифтов обязателен всегда.
- Preconnect к десяткам доменов. Каждое соединение конкурирует за полосу и память. Держите 4–6 максимум.
- Preload ресурса не для текущей страницы. Это работа prefetch. Preload — только то, что нужно прямо сейчас.
- Прелоад всех шрифтов сразу. Грейте только тот шрифт, который виден на первом экране, остальные пусть подгружаются естественно.
- Неправильный атрибут as. Без корректного as приоритет и CORS-политика выставляются неверно, возможна двойная загрузка.
- fetchpriority high на всём. Если всё высокоприоритетное — приоритетов нет. Повышайте только LCP-элемент.
- 103 на сайте с низким TTFB. Усложнение без выигрыша, иногда с риском несовместимости старых прокси.
- Игнор предупреждений консоли. «Preloaded but not used» — это прямой указатель на лишний хинт.
Отдельно подчеркнём про шрифты: типичная картина — разработчик прелоадит четыре начертания (regular, bold, italic, bold-italic), хотя на первом экране используется только regular. Три лишних прелоада забивают канал в самый критичный момент. Прогревайте ровно то, что рендерится в зоне LCP.
Итоги и с чего начать
Прогрев загрузки — это точная инженерная работа, а не набор магических тегов. Resource hints и 103 Early Hints дают реальный выигрыш в LCP и косвенно в INP, но только при дисциплинированном подходе: сначала анализ критического пути, потом точечные хинты под конкретные узкие места, затем измерение и чистка. Перегрев хинтами замедляет сайт так же надёжно, как их полное отсутствие. Правило простое — грейте мало, но точно: критичный шрифт, LCP-картинку, 2–4 ключевых соединения. Всё остальное браузер прекрасно обнаружит сам.
Если хотите, чтобы прогрев загрузки разобрали специалисты и встроили в общую стратегию ускорения, закажите комплексный SEO-аудит сайта — мы найдём узкие места критического пути и составим план оптимизации. А чтобы скорость загрузки превратилась в рост позиций и трафика, подключите профессиональное SEO-продвижение сайта под ключ.
Услуги LSI Продвижение
Наша команда предлагает полный спектр услуг по SEO-продвижению и технической доработке сайтов. Мы работаем только белыми методами, ориентируемся на реальный бизнес-результат — трафик, заявки и продажи, а не только позиции в отчёте, — и выстраиваем продвижение системно, под конкретные задачи и нишу вашего проекта. Начать можно с бесплатной диагностики, чтобы понять текущее состояние сайта и точки роста, а затем перейти к комплексной работе. Выберите подходящую услугу из списка ниже:
- Бесплатный SEO аудит сайта — автоматическая проверка на 50+ параметров за 2 минуты
- Комплексный SEO аудит — глубокий ручной анализ с рекомендациями от эксперта
- Продвижение сайтов — вывод в ТОП Яндекса и Google по целевым запросам
- SEO консультация — разбор вашего сайта с конкретными рекомендациями
- LSI тексты — экспертный контент, оптимизированный для поисковых систем
- Доработка сайта — техническая оптимизация и исправление ошибок
- Создание сайта под ключ — разработка с нуля с SEO-оптимизацией
- Стоимость продвижения — прозрачные тарифы и условия
- Портфолио и кейсы — реальные результаты наших клиентов
Закажите SEO продвижение сайта
Выведем ваш сайт в ТОП Яндекса и Google. Бесплатная консультация — разберём сайт, найдём точки роста и предложим стратегию продвижения.
Comments
Всегда путал preload и prefetch, теперь разложилось: preload для критичного здесь и сейчас, prefetch для того, что понадобится на следующей странице. Спасибо за чёткое разделение.
Добавила preconnect к домену со шрифтами и preload для основного шрифта — мигание текста (тот самый FOIT) почти ушло, LCP стал ровнее. Мелочь, а эффект заметный.
А 103 Early Hints уже реально где-то работает или это пока экзотика? Мой хостинг про такое, кажется, даже не слышал. На чём его вообще можно включить?
Виктор, 103 Early Hints уже не экзотика: их поддерживают Cloudflare (включается в панели), свежие версии Nginx с модулем и ряд облачных хостингов. На типовом шаред-хостинге действительно может не быть, но если вы за Cloudflare — включается почти без усилий. Начните с preconnect и preload в Early Hints для шрифта и LCP-картинки, это самый заметный выигрыш.
Не совсем поняла разницу между dns-prefetch и preconnect. Preconnect ведь тоже резолвит DNS? Зачем тогда отдельный dns-prefetch, если preconnect делает больше?
Жанна, вы правы, что preconnect делает больше — он и DNS резолвит, и TCP-соединение с TLS устанавливает заранее. dns-prefetch нужен как более лёгкий и широко поддерживаемый вариант: он только резолвит DNS. Обычно их ставят в паре как fallback — preconnect для критичных доменов, dns-prefetch для остальных, к которым обращение вероятно, но не факт.
Переборщил с preload когда-то — напихал десяток ресурсов, и стало только хуже, всё конкурировало за канал. Хорошо, что в статье есть раздел про типичные ошибки, это прям больная тема.
Про fetchpriority впервые слышу. Это тот самый атрибут, которым можно поднять приоритет LCP-картинки? Можете показать, как он в разметке выглядит?
У меня INP плохой, а не LCP. Из статьи понял, что хинты в основном про загрузку. Есть ли от них польза для интерактивности или тут надо другое лечить?
Семён, верно — resource hints лечат загрузку (LCP, скорость первой отрисовки), а не интерактивность. INP упирается в тяжёлый JavaScript, который блокирует главный поток. Тут нужно другое: разбивка длинных задач, дефер и удаление лишних скриптов, code splitting. Хинты помогут косвенно, разгрузив сеть, но корень INP — в исполнении JS.
Спасибо за пошаговый алгоритм «что и когда греть». Наконец понятно, что не надо гнать preload на всё подряд, а начать с одного-двух критичных ресурсов на LCP.
Вопрос по modulepreload: если у меня сайт на Vue и куча ES-модулей, реально ли это ускорит их подгрузку? Или браузер и так их достаточно быстро тянет?
У меня была ровно проблема из вступления — теряли сотни миллисекунд на критическом пути из-за позднего подключения к CDN. preconnect к CDN эти задержки срезал. Работает.
А как понять, какой именно ресурс греть? В DevTools смотреть водопад загрузки? Хочется методику, а не гадание, что тут критичное, а что нет.
Матвей, методика простая: откройте DevTools → Performance или водопад в Network, найдите LCP-элемент (Lighthouse его прямо подсвечивает) и посмотрите, что грузится перед ним и с какой задержкой. Греть нужно то, что лежит на критическом пути к LCP: главную картинку, ключевой шрифт, критичный CSS. Всё остальное — по остаточному принципу, без фанатизма.
Немного сомневаюсь насчёт prefetch: не тратим ли мы трафик пользователя на загрузку страниц, которые он, может, и не откроет? Особенно на мобильном это же деньги.
Прочитал про Early Hints и загорелся. Оказалось, Cloudflare умеет их отдавать автоматически. Включил — TTFB формально тот же, а вот отрисовка началась раньше.
Отличная статья. Единственное, чего не хватило — примера, как не переусердствовать. Сколько preload это уже много? Есть какое-то правило большого пальца?
Вероника, правило большого пальца — preload только для того, что действительно на критическом пути и что браузер обнаружит поздно (обычно 1–3 ресурса: LCP-картинка, критичный шрифт, иногда ключевой скрипт). Если preload-ов больше пяти, почти наверняка вы уже вредите: они начинают конкурировать за канал и отодвигают друг друга. Меньше, но точнее.
Внедрил fetchpriority=»high» на баннер в первом экране и убрал preload с фонового изображения. LCP улучшился на глаз и по замерам. Мелкие атрибуты, а решают.
Спасибо за раздел про приоритеты ресурсов. Раньше думала, что браузер сам всё расставит правильно, а оказывается, ему можно и нужно подсказывать.
А resource hints не мешают кешированию? Если ресурс уже в кеше, preload его повторно не потянет впустую?
Оставить комментарий
Мы используем cookies
Для улучшения работы сайта и вашего удобства. Оставаясь на сайте, вы соглашаетесь с политикой конфиденциальности.