Ускоренная загрузка страниц за счет времени на размышление сервера с помощью Early Hints

Узнайте, как ваш сервер может отправлять браузеру подсказки о важных субресурсах.

Что такое ранние подсказки?

Веб-сайты со временем стали более сложными. Таким образом, нет ничего необычного в том, что серверу необходимо выполнить нетривиальную работу (например, доступ к базам данных или CDN, обращающимся к исходному серверу) для создания HTML для запрошенной страницы. К сожалению, это «время на размышление сервера» приводит к дополнительной задержке, прежде чем браузер сможет начать отображать страницу. Действительно, соединение фактически простаивает до тех пор, пока сервер готовит ответ.

Изображение показывает временной интервал мышления сервера в 200 мс между загрузкой страницы и загрузкой других ресурсов.
Без ранних подсказок: на сервере все блокируется, определяя, как реагировать на основной ресурс.

Early Hints — это код состояния HTTP ( 103 Early Hints ), используемый для отправки предварительного HTTP-ответа перед окончательным ответом. Это позволяет серверу отправлять подсказки браузеру о критических подресурсах (например, таблицах стилей для страницы, критическом JavaScript) или источниках, которые, вероятно, будут использоваться страницей, пока сервер занят созданием основного ресурса. Браузер может использовать эти подсказки для разогрева соединений и запроса подресурсов во время ожидания основного ресурса. Другими словами, Early Hints помогает браузеру воспользоваться таким «временем на обдумывание сервера», заранее проделав некоторую работу, тем самым ускоряя загрузку страниц.

Изображение, показывающее, как Early Hints позволяет странице отправлять частичный ответ.
С ранними подсказками: сервер может предоставлять частичный ответ с подсказками по ресурсам, пока он определяет окончательный ответ.

В некоторых случаях улучшение производительности при использовании Largest Contentful Paint может достигать нескольких сотен миллисекунд, как наблюдают Shopify и Cloudflare , и до секунды быстрее, как видно из сравнения до и после:

Сравнение двух сайтов.
Сравнение ранних подсказок до и после на тестовом веб-сайте, выполненное с помощью WebPageTest (Moto G4 — DSL)

Как использовать ранние подсказки

Первый шаг к использованию Early Hints состоит в определении самых популярных целевых страниц, то есть страниц, с которых ваши пользователи обычно начинают, когда посещают ваш сайт. Это может быть домашняя страница или страницы со списком популярных продуктов, если на ваш сайт приходит много пользователей с других веб-сайтов. Причина, по которой эти точки входа имеют большее значение, чем другие страницы, заключается в том, что полезность ранних подсказок снижается по мере того, как пользователь перемещается по вашему веб-сайту (то есть, браузер с большей вероятностью будет иметь все необходимые подресурсы при второй или третьей последующей навигации). Также всегда полезно произвести хорошее первое впечатление!

Теперь, когда у вас есть список приоритетных целевых страниц, следующим шагом будет определение источников или подресурсов, которые будут подходящими кандидатами для подсказок preconnect или preload . Обычно это источники и подресурсы, которые в наибольшей степени влияют на ключевые пользовательские метрики, такие как «Наибольшая отрисовка контента» или «Первая отрисовка контента» . Более конкретно, ищите подресурсы, блокирующие рендеринг, такие как синхронный JavaScript, таблицы стилей или даже веб-шрифты. Аналогичным образом ищите источники, на которых размещены подресурсы, которые вносят большой вклад в ключевые показатели пользователя.

Также обратите внимание: если ваши основные ресурсы уже используют preconnect или preload , вы можете рассмотреть эти источники или ресурсы среди кандидатов на ранние подсказки. Узнайте больше о том, как оптимизировать LCP . Однако простое копирование директив preconnect и preload из HTML в Early Hints может оказаться неоптимальным .

При их использовании в HTML обычно требуется preconnect или preload ресурсы, которые сканер предварительной загрузки не обнаружит в HTML, например шрифты или фоновые изображения, которые в противном случае были бы обнаружены поздно. Для ранних подсказок у вас не будет HTML-кода, поэтому вместо этого вы можете захотеть preconnect к критически важным доменам или preload критические ресурсы, которые в противном случае, возможно, были бы обнаружены на ранней стадии HTML, например, предварительная загрузка main.css или app.js Кроме того, не все браузеры поддерживают preload Early Hints — см. «Поддержка браузера» .

Второй шаг состоит в минимизации риска использования Early Hints для ресурсов или источников, которые могут быть устаревшими или больше не использоваться основным ресурсом. Например, ресурсы, которые часто обновляются и имеют версии (например, example.com/css/main.fa231e9c.css ), могут быть не лучшим выбором. Обратите внимание, что эта проблема касается не только Early Hints, она относится к любой preload или preconnect где бы они ни присутствовали. Это тот вид детализации, который лучше всего решается с помощью автоматизации или шаблонизации (например, ручной процесс с большей вероятностью приведет к несовпадению хеша или URL-адресов версий между preload и фактическим HTML-тегом, использующим ресурс).

В качестве примера рассмотрим следующий поток:

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]

Сервер предсказывает, что понадобится main.abcd100.css , и предлагает предварительно загрузить его с помощью Early Hints:

103 Early Hints
Link: </main.abcd100.css>; rel=preload; as=style
[...]

Через несколько мгновений отображается веб-страница, включая связанный CSS. К сожалению, этот ресурс CSS часто обновляется, и основной ресурс уже на пять версий опережает прогнозируемый ресурс CSS ( abcd105 ) ( abcd100 ).

200 OK
[...]
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.abcd105.css">

В общем, стремитесь к ресурсам и источникам, которые достаточно стабильны и в значительной степени независимы от результата для основного ресурса. При необходимости вы можете рассмотреть возможность разделения ключевых ресурсов на две части: стабильную часть, предназначенную для использования с Early Hints, и более динамичную часть, которую нужно получить после того, как основной ресурс будет получен браузером:

<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">

Наконец, на стороне сервера найдите запросы основных ресурсов, отправленные браузерами, которые поддерживают Early Hints, и немедленно ответьте 103 Early Hints. В ответ 103 включите соответствующие подсказки по предварительному подключению и предварительной загрузке. Как только основной ресурс будет готов, отправьте обычный ответ (например, 200 OK в случае успеха). В целях обратной совместимости рекомендуется также включать HTTP-заголовки Link в окончательный ответ, возможно, даже дополняя их критически важными ресурсами, которые стали очевидными при создании основного ресурса (например, динамическая часть ключевого ресурса, если вы следовали инструкциям " предложение разделить на две части). Вот как это будет выглядеть:

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]
103 Early Hints
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script

Несколько мгновений спустя:

200 OK
Content-Length: 7531
Content-Type: text/html; charset=UTF-8
Content-encoding: br
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script
Link: </experimental.3eab3290.css>; rel=preload; as=style
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">
   <script src="/common.js"></script>
   <link rel="preconnect" href="https://fonts.googleapis.com">

Поддержка браузера

Хотя 103 Early Hints поддерживается во всех основных браузерах, директивы, которые можно отправлять в Early Hint, различаются в зависимости от браузера:

Поддержка предварительного подключения:

Поддержка браузера

  • Хром: 103.
  • Край: 103.
  • Фаерфокс: 120.
  • Сафари: 17.

Поддержка предварительной загрузки:

Поддержка браузера

  • Хром: 103.
  • Край: 103.
  • Фаерфокс: 123.
  • Сафари: не поддерживается.

Chrome DevTools также поддерживает 103 Early Hints , а заголовки Link можно увидеть в ресурсах документа:

Панель сети, показывающая заголовки ранних подсказок
Заголовки Link Early Hints отображаются в Chrome DevTools.

Обратите внимание, что для использования ресурсов Early Hints Disable cache не должен быть отмечен в DevTools, поскольку Early Hints использует кеш браузера. Для предварительно загруженных ресурсов инициатор будет отображаться как early-hints , а размер — как (Disk cache) :

Сетевая панель, показывающая инициаторов Early Hints
Ресурсы Early Hinted имеют инициатор early-hints и загружаются из дискового кэша.

Для этого также требуется доверенный сертификат для тестирования HTTPS.

Firefox (начиная с версии 126) не имеет явной поддержки 103 Early Hints в DevTools, но ресурсы, загруженные с помощью Early Hints, не отображают информацию заголовка HTTP, что является одним из индикаторов того, что они были загружены с помощью Early Hints.

Поддержка сервера

Вот краткий обзор уровня поддержки Early Hints среди популярного программного обеспечения с открытым исходным кодом HTTP-сервера:

Включите ранние подсказки более простым способом

Если вы используете одну из следующих сетей CDN или платформ, вам, возможно, не потребуется вручную внедрять Early Hints. Обратитесь к онлайн-документации вашего поставщика решений, чтобы узнать, поддерживает ли он Early Hints, или обратитесь к неполному списку здесь:

Как избежать проблем для клиентов, которые не поддерживают Early Hints

Информационные ответы HTTP в диапазоне 100 являются частью стандарта HTTP, но некоторые старые клиенты или боты могут с этим столкнуться, поскольку до запуска 103 Early Hints они редко использовались для общего просмотра веб-страниц.

Выдача только 103 ранних подсказок в ответ на клиенты, которые отправляют заголовок HTTP-запроса sec-fetch-mode: navigate должна гарантировать, что такие подсказки отправляются только для новых клиентов, которые понимают, что нужно ждать последующего ответа. Кроме того, поскольку ранние подсказки поддерживаются только для запросов навигации (см. текущие ограничения ), это дает дополнительное преимущество, позволяющее избежать ненужной отправки их по другим запросам.

Кроме того, ранние подсказки рекомендуется отправлять только через соединения HTTP/2 или HTTP/3 , и большинство браузеров принимают их только по этим протоколам.

Расширенный шаблон

Если вы полностью применили Early Hints к своим ключевым целевым страницам и ищете больше возможностей, вас может заинтересовать следующий расширенный шаблон.

Для посетителей, которые запрашивают n-ю страницу в рамках типичного пользовательского путешествия, вы можете адаптировать ответ Early Hints к содержимому, которое находится ниже и глубже на странице, другими словами, используя Early Hints на ресурсах с более низким приоритетом. Это может показаться нелогичным, учитывая, что мы рекомендовали сосредоточиться на высокоприоритетных подресурсах или источниках, блокирующих рендеринг. Однако к тому времени, как посетитель какое-то время перемещается по сайту, весьма вероятно, что в его браузере уже есть все важные ресурсы. С этого момента, возможно, имеет смысл переключить ваше внимание на ресурсы с более низким приоритетом. Например, это может означать использование Early Hints для загрузки изображений продуктов или дополнительных JS/CSS, которые необходимы только для менее частых взаимодействий с пользователем.

Текущие ограничения

Вот ограничения Early Hints, реализованные в Chrome:

  • Доступен только для запросов навигации (т. е. основной ресурс для документа верхнего уровня).
  • Поддерживается только preconnect и preload (то есть prefetch не поддерживается).
  • Ранние подсказки, за которыми следует перенаправление между источниками в окончательном ответе, приведут к тому, что Chrome удалит ресурсы и соединения, полученные с помощью ранних подсказок.
  • Ресурсы, предварительно загруженные с помощью Early Hints, сохраняются в HTTP-кеше и извлекаются оттуда страницей позже. Поэтому только кэшируемые ресурсы могут быть предварительно загружены с помощью Early Hints, иначе ресурс будет получен дважды (один раз с помощью Early Hints и снова документом). В Chrome HTTP-кеш отключен для ненадежных сертификатов HTTPS (даже если вы продолжите загрузку страницы).
  • Предварительная загрузка адаптивных изображений (с использованием imagesrcset , imagesizes или media ) не поддерживается с использованием заголовков HTTP <link> , поскольку область просмотра не определена до тех пор, пока документ не будет создан. Это означает, что 103 Ранние подсказки нельзя использовать для предварительной загрузки адаптивных изображений, и при их использовании можно загрузить неправильное изображение. Следите за обсуждением предложений о том, как лучше с этим справиться .

Другие браузеры имеют аналогичные ограничения, и, как отмечалось ранее , некоторые дополнительно ограничивают 103 ранних подсказки только preconnect .

Что дальше?

В зависимости от интереса сообщества мы можем дополнить нашу реализацию Early Hints следующими возможностями:

  • Ранние подсказки для некэшируемых ресурсов, использующих кеш памяти, а не кеш HTTP.
  • Ранние подсказки отправляются по запросам субресурсов.
  • Ранние подсказки отправляются по запросам основных ресурсов iframe.
  • Поддержка предварительной выборки в Early Hints.

Мы приветствуем ваше мнение о том, каким аспектам следует уделять приоритетное внимание и как дальше улучшать Early Hints.

Связь с H2/Push

Если вы знакомы с устаревшей функцией HTTP2/Push , вы можете задаться вопросом, чем отличаются Early Hints. В то время как Early Hints требует, чтобы браузер начал получать критические подресурсы в обе стороны, с помощью HTTP2/Push сервер может начать отправлять подресурсы вместе с ответом. Хотя это звучит потрясающе, это привело к ключевому структурному недостатку: при использовании HTTP2/Push было чрезвычайно сложно избежать передачи подресурсов, которые уже были в браузере. Этот эффект «чрезмерного давления» привел к менее эффективному использованию пропускной способности сети, что значительно снизило преимущества в производительности. В целом данные Chrome показали, что HTTP2/Push на самом деле отрицательно влияет на производительность в сети.

Напротив, Early Hints на практике работает лучше, поскольку сочетает в себе возможность отправки предварительного ответа с подсказками, которые позволяют браузеру получать или подключаться к тому, что ему действительно нужно. Хотя Early Hints не охватывает все случаи использования, которые теоретически может реализовать HTTP2/Push, мы считаем, что Early Hints — более практичное решение для ускорения навигации.

Миниатюрное изображение Пьера Бамина .