Разработка сайтов, которые будут быстры везде, может быть сложной задачей. Изобилие возможностей устройств и качество сетей, к которым они подключаются, могут сделать это непреодолимой задачей. Хотя мы можем использовать возможности браузера для повышения производительности загрузки, как мы узнаем, на что способно устройство пользователя или каково качество его сетевого соединения? Решение — клиентские подсказки !
Подсказки клиента — это набор заголовков HTTP-запросов, которые дают нам представление об этих аспектах устройства пользователя и сети, к которой он подключен. Подключаясь к этой информации на стороне сервера, мы можем изменить способ доставки контента в зависимости от состояния устройства и/или сети. Это может помочь нам создать более инклюзивный пользовательский опыт.
Все дело в согласовании контента
Клиентские подсказки — это еще один метод согласования контента , который подразумевает изменение ответов контента на основе заголовков запросов браузера.
Один из примеров согласования контента включает заголовок запроса Accept
. Он описывает, какие типы контента понимает браузер, которые сервер может использовать для согласования ответа. Для запросов изображений содержимое заголовка Accept
Chrome следующее:
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Хотя все браузеры поддерживают такие форматы изображений, как JPEG, PNG и GIF, Accept в этом случае сообщает, что браузер также поддерживает WebP и APNG . Используя эту информацию, мы можем договориться о лучших типах изображений для каждого браузера:
<?php
// Check Accept for an "image/webp" substring.
$webp = stristr($_SERVER["HTTP_ACCEPT"], "image/webp") !== false ? true : false;
// Set the image URL based on the browser's WebP support status.
$imageFile = $webp ? "whats-up.webp" : "whats-up.jpg";
?>
<img src="<?php echo($imageFile); ?>" alt="I'm an image!">
Как и Accept
, клиентские подсказки являются еще одним способом согласования контента, но в контексте возможностей устройства и условий сети. С клиентскими подсказками мы можем принимать решения о производительности на стороне сервера на основе индивидуального опыта пользователя, например, решать, следует ли предоставлять некритические ресурсы пользователям с плохими условиями сети. В этом руководстве мы опишем все доступные подсказки и некоторые способы их использования для того, чтобы сделать доставку контента более удобной для пользователей.
Выбрав в
В отличие от заголовка Accept
, клиентские подсказки не появляются просто так, по волшебству (за исключением Save-Data
, который мы обсудим позже). В интересах сохранения заголовков запроса на минимуме вам нужно будет выбрать, какие клиентские подсказки вы хотите получать, отправив заголовок Accept-CH
когда пользователь запрашивает ресурс:
Accept-CH: Viewport-Width, Downlink
Значение Accept-CH
— это разделенный запятыми список запрошенных подсказок, которые сайт будет использовать при определении результатов для последующего запроса ресурсов. Когда клиент читает этот заголовок, ему говорят: «Этот сайт хочет клиентские подсказки Viewport-Width
и Downlink
». Не беспокойтесь о конкретных подсказках. Мы доберемся до них через минуту.
Вы можете установить эти заголовки opt-in на любом языке back-end. Например, можно использовать функцию header
PHP . Вы даже можете установить эти заголовки opt-in с помощью атрибута http-equiv
в теге <meta>
:
<meta http-equiv="Accept-CH" content="Viewport-Width, Downlink" />
Все подсказки клиентов!
Подсказки клиента описывают одну из двух вещей: устройство, которое ваши пользователи, ну, используют , и сеть, которую они используют для доступа к вашему сайту. Давайте кратко рассмотрим все подсказки, которые доступны.
Подсказки по устройству
Некоторые клиентские подсказки описывают характеристики устройства пользователя, обычно характеристики экрана. Некоторые из них могут помочь вам выбрать оптимальный медиаресурс для экрана данного пользователя, но не все из них обязательно медиацентричны.
Прежде чем перейти к этому списку, будет полезно узнать несколько ключевых терминов, используемых для описания экранов и разрешения носителей:
Внутренний размер: фактические размеры медиаресурса. Например, если вы открываете изображение в Photoshop, размеры, показанные в диалоговом окне размера изображения, описывают его внутренний размер .
Собственный размер с поправкой на плотность: размеры медиаресурса после того, как он был скорректирован на плотность пикселей. Это собственный размер изображения, деленный на соотношение пикселей устройства . Например, возьмем эту разметку:
<img
src="whats-up-1x.png"
srcset="whats-up-2x.png 2x, whats-up-1x.png 1x"
alt="I'm that image you wanted."
/>
Допустим, что внутренний размер изображения 1x
в этом случае составляет 320x240, а внутренний размер изображения 2x
составляет 640x480. Если эта разметка анализируется клиентом, установленным на устройстве с соотношением пикселей экрана устройства 2 (например, экран Retina), запрашивается изображение 2x
. Скорректированный по плотности внутренний размер изображения 2x
составляет 320x240, поскольку 640x480, деленное на 2, дает 320x240.
Внешний размер: размер медиаресурса после применения к нему CSS и других факторов макета (таких как атрибуты width
и height
). Допустим, у вас есть элемент <img>
, который загружает изображение с скорректированным по плотности внутренним размером 320x240, но к нему также применены свойства CSS width
и height
со значениями 256px
и 192px
соответственно. В этом примере внешний размер этого элемента <img>
становится 256x192.
width: 256px;
и height: 192px;
преобразует изображение внутреннего размера 320x240 в изображение внешнего размера 256x192.Освоив некоторую терминологию, давайте перейдем к списку доступных вам клиентских советов для конкретных устройств.
Ширина области просмотра
Viewport-Width
— ширина области просмотра пользователя в пикселях CSS:
Viewport-Width: 320
Эту подсказку можно использовать вместе с другими подсказками, зависящими от экрана, для предоставления различных обработок (например, кадрирования) изображения, которые оптимальны для определенных размеров экрана (например, художественное направление ), или для исключения ресурсов, которые не нужны для текущей ширины экрана.
ДНР
DPR
(сокращение от device pixel ratio) сообщает соотношение физических пикселей к CSS-пикселям экрана пользователя:
DPR: 2
Эта подсказка полезна при выборе источников изображений, которые соответствуют плотности пикселей экрана (как это делают дескрипторы x
в атрибуте srcset
).
Ширина
Подсказка Width
отображается в запросах на ресурсы изображений, отправляемых тегами <img>
или <source>
с использованием атрибута sizes
. sizes
сообщает браузеру, каким будет внешний размер ресурса; Width
использует этот внешний размер для запроса изображения с внутренним размером, оптимальным для текущего макета.
Например, предположим, что пользователь запрашивает страницу с экраном шириной 320 пикселей CSS с DPR 2. Устройство загружает документ с элементом <img>
, содержащим значение атрибута sizes
85vw
(т.е. 85% ширины области просмотра для всех размеров экрана). Если подсказка Width
была включена, клиент отправит эту подсказку Width
на сервер с запросом src
<img>
:
Width: 544
В этом случае клиент намекает серверу, что оптимальная внутренняя ширина запрошенного изображения будет составлять 85% ширины области просмотра (272 пикселя), умноженной на DPR экрана (2), что равно 544 пикселям.
Эта подсказка особенно мощна, поскольку она не только учитывает скорректированную по плотности ширину экрана, но и согласовывает эту важную часть информации с внешним размером изображения в макете. Это дает серверам возможность согласовывать ответы изображения, которые оптимальны как для экрана , так и для макета.
Контент-DPR
Хотя вы уже знаете, что экраны имеют пиксельное соотношение устройства, ресурсы также имеют свои собственные пиксельные соотношения. В простейших случаях использования выбора ресурсов пиксельные соотношения между устройствами и ресурсами могут быть одинаковыми. Но! В случаях, когда задействованы оба заголовка DPR
и Width
, внешний размер ресурса может создавать сценарии, в которых они различаются. Вот где в игру вступает подсказка Content-DPR
.
В отличие от других клиентских подсказок, Content-DPR
не является заголовком запроса , который должен использоваться серверами, а скорее заголовком ответа , который серверы должны отправлять всякий раз, когда подсказки DPR
и Width
используются для выбора ресурса. Значение Content-DPR
должно быть результатом этого уравнения:
Content-DPR
= [Выбранный размер ресурса изображения] / ([ Width
] / [ DPR
])
При отправке заголовка запроса Content-DPR
браузер будет знать, как масштабировать данное изображение для соотношения пикселей экрана устройства и макета. Без этого изображения могут масштабироваться некорректно.
Устройство-Память
Технически являясь частью API памяти устройства , Device-Memory
показывает приблизительный объем памяти текущего устройства в ГиБ:
Device-Memory: 2
Возможным вариантом использования этой подсказки может быть уменьшение количества JavaScript, отправляемого браузерам на устройствах с ограниченной памятью, поскольку JavaScript является наиболее ресурсоемким типом контента, который обычно загружают браузеры . Или вы можете отправлять изображения с более низким DPR, поскольку они используют меньше памяти для декодирования.
Сетевые подсказки
API сетевой информации предоставляет еще одну категорию клиентских подсказок, которые описывают производительность сетевого соединения пользователя. По моему мнению, это самый полезный набор подсказок. С ними у нас есть возможность адаптировать опыт для пользователей, изменяя способ доставки ресурсов клиентам при медленных соединениях.
РТТ
Подсказка RTT
обеспечивает приблизительное время кругового пути в миллисекундах на уровне приложения. Подсказка RTT
, в отличие от RTT транспортного уровня, включает время обработки сервера.
RTT: 125
Эта подсказка полезна из-за роли задержки в производительности загрузки. Используя подсказку RTT
, мы можем принимать решения на основе отклика сети, что может помочь ускорить доставку всего опыта (например, путем пропуска некоторых запросов).
Нисходящая линия связи
Хотя задержка важна для производительности загрузки, пропускная способность также имеет значение. Подсказка Downlink
, выраженная в мегабитах в секунду (Мбит/с), показывает приблизительную скорость нисходящего потока соединения пользователя:
Downlink: 2.5
В сочетании с RTT
Downlink
может быть полезен для изменения способа доставки контента пользователям в зависимости от качества сетевого соединения.
ЭСТ
Подсказка ECT
означает Effective Connection Type (эффективный тип соединения) . Ее значение — один из пронумерованного списка типов соединения, каждый из которых описывает соединение в указанных диапазонах значений RTT
и Downlink
.
Этот заголовок не объясняет, каков фактический тип соединения, например, он не сообщает, является ли ваш шлюз вышкой сотовой связи или точкой доступа Wi-Fi. Вместо этого он анализирует задержку и пропускную способность текущего соединения и определяет, какой сетевой профиль больше всего похож. Например, если вы подключаетесь через Wi-Fi к медленной сети, ECT
может быть заполнен значением 2g
, что является ближайшим приближением к эффективному соединению:
ECT: 2g
Допустимые значения для ECT
: 4g
, 3g
, 2g
и slow-2g
. Эту подсказку можно использовать в качестве отправной точки для оценки качества соединения, а затем уточнить с помощью подсказок RTT
и Downlink
.
Сохранить данные
Save-Data
— это не столько подсказка, описывающая состояние сети, сколько настройка пользователя, указывающая, что страницы должны отправлять меньше данных.
Я предпочитаю классифицировать Save-Data
как сетевую подсказку, потому что многие из действий, которые вы можете с ней выполнить, похожи на другие сетевые подсказки. Пользователи также могут включать ее в средах с высокой задержкой/низкой пропускной способностью. Эта подсказка, если она присутствует, всегда выглядит так:
Save-Data: on
Здесь, в Google, мы говорили о том, что вы можете сделать с помощью Save-Data
. Влияние, которое оно может оказать на производительность, может быть значительным. Это сигнал, когда пользователи буквально просят вас отправлять им меньше информации! Если вы прислушаетесь к этому сигналу и отреагируете на него, пользователи это оценят.
Связываем все вместе
Что вы будете делать с клиентскими подсказками, зависит от вас. Поскольку они предлагают так много информации, у вас есть много вариантов. Чтобы получить некоторые идеи, давайте посмотрим, что клиентские подсказки могут сделать для Sconnie Timber , вымышленной лесозаготовительной компании, расположенной в сельской местности Верхнего Среднего Запада. Как это часто бывает в отдаленных районах , сетевые соединения могут быть хрупкими. Именно здесь такая технология, как клиентские подсказки, может действительно иметь значение для пользователей.
Адаптивные изображения
Все, кроме самых простых вариантов использования адаптивных изображений, могут быть сложными. Что делать, если у вас есть несколько вариантов обработки и вариантов одних и тех же изображений для разных размеров экрана и разных форматов? Такая разметка очень быстро становится очень сложной . Легко ошибиться, легко забыть или неправильно понять важные концепции (например, sizes
).
Хотя <picture>
и srcset
несомненно, являются потрясающими инструментами, их разработка и поддержка для сложных случаев использования могут потребовать много времени. Мы можем автоматизировать генерацию разметки, но сделать это также сложно, поскольку функциональность, предоставляемая <picture>
и srcset
достаточно сложна, поэтому их автоматизация должна осуществляться таким образом, чтобы сохранить гибкость, которую они предоставляют.
Клиентские подсказки могут упростить это. Согласование ответов изображений с клиентскими подсказками может выглядеть примерно так:
- Если это применимо к вашему рабочему процессу, сначала выберите обработку изображения (например, художественно-ориентированное изображение), проверив подсказку
Viewport-Width
. - Выберите разрешение изображения, проверив подсказку «
Width
и подсказкуDPR
, а также выбрав источник, который соответствует размеру макета изображения и плотности экрана (аналогично тому, как работают дескрипторыx
иw
вsrcset
). - Выберите наиболее оптимальный формат файла, поддерживаемый браузером (в большинстве браузеров нам помогает это сделать
Accept
).
Что касается моего вымышленного клиента лесозаготовительной компании, я разработал наивную адаптивную процедуру выбора изображений на PHP, которая использует клиентские подсказки. Это означало, что вместо отправки этой разметки всем пользователям:
<picture>
<source
srcset="
company-photo-256w.webp 256w,
company-photo-512w.webp 512w,
company-photo-768w.webp 768w,
company-photo-1024w.webp 1024w,
company-photo-1280w.webp 1280w
"
type="image/webp"
/>
<img
srcset="
company-photo-256w.jpg 256w,
company-photo-512w.jpg 512w,
company-photo-768w.jpg 768w,
company-photo-1024w.jpg 1024w,
company-photo-1280w.jpg 1280w
"
src="company-photo-256w.jpg"
sizes="(min-width: 560px) 251px, 88.43vw"
alt="The Sconnie Timber Staff!"
/>
</picture>
Мне удалось сократить его до следующего, основываясь на поддержке отдельных браузеров:
<img
src="/image/sizes:true/company-photo.jpg"
sizes="(min-width: 560px) 251px, 88.43vw"
alt="SAY CHEESY PICKLES."
/>
В этом примере URL-адрес /image
— это PHP-скрипт, за которым следуют параметры, переписанные mod_rewrite . Он принимает имя файла изображения и дополнительные параметры, чтобы помочь внутреннему скрипту выбрать лучшее изображение в заданных условиях.
Я чувствую, что ваш первый вопрос: «Но разве это не просто повторная реализация <picture>
и srcset
на бэкенде?»
В некотором смысле, да, но с важным отличием: когда приложение использует клиентские подсказки для создания медиа-ответов, большую часть (если не всю) работы гораздо проще автоматизировать, что может включать службу (такую как CDN), которая может делать это от вашего имени. В то время как в случае с HTML-решениями необходимо писать новую разметку для обеспечения каждого варианта использования. Конечно, вы можете автоматизировать генерацию разметки. Однако если ваш дизайн или требования изменятся, есть большая вероятность, что вам придется пересмотреть свою стратегию автоматизации в будущем.
Клиентские подсказки позволяют начать с изображения высокого разрешения без потерь, размер которого затем можно динамически изменять, чтобы он был оптимальным для любой комбинации экрана и макета. В отличие от srcset
, который требует от вас перечисления фиксированного списка возможных кандидатов на изображения для выбора браузером, этот подход может быть более гибким. В то время как srcset
заставляет вас предлагать браузерам грубый набор вариантов — скажем, 256w
, 512w
, 768w
и 1024w
— решение на основе клиентских подсказок может обслуживать все ширины без гигантской кучи разметки.
Конечно, вам не нужно писать логику выбора изображений самостоятельно. Cloudinary использует клиентские подсказки для создания ответов изображений, когда вы используете параметр w_auto
, и заметил, что медианные пользователи загружали на 42% меньше байтов при использовании браузеров, поддерживающих клиентские подсказки.
Но будьте осторожны! Изменения в настольной версии Chrome 67 убрали поддержку подсказок для клиентов с разными источниками . К счастью, эти ограничения не затрагивают мобильные версии Chrome, и они будут сняты для всех платформ, когда работа над Feature Policy будет завершена.
Помощь пользователям в медленных сетях
Идея адаптивной производительности заключается в том, что мы можем корректировать способ предоставления ресурсов на основе информации, которую нам предоставляют клиентские подсказки; в частности, информации о текущем состоянии сетевого подключения пользователя.
Что касается сайта Sconnie Timber, мы предпринимаем шаги для снижения нагрузки при медленной работе сетей, проверяя заголовки Save-Data
, ECT
, RTT
и Downlink
в нашем внутреннем коде. Когда это сделано, мы генерируем оценку качества сети, которую можем использовать для определения того, следует ли нам вмешаться для улучшения пользовательского опыта. Эта оценка сети находится в диапазоне от 0
до 1
, где 0
— наихудшее возможное качество сети, а 1
— наилучшее.
Сначала мы проверяем, присутствует ли Save-Data
. Если да, то оценка устанавливается на 0
, так как мы предполагаем, что пользователь хочет, чтобы мы сделали все необходимое, чтобы сделать опыт легче и быстрее.
Однако если Save-Data
отсутствует, мы идем дальше и взвешиваем значения подсказок ECT
, RTT
и Downlink
для вычисления оценки, описывающей качество сетевого соединения. Исходный код генерации сетевой оценки доступен на Github. Вывод таков: если мы используем подсказки, связанные с сетью, каким-либо образом, мы можем улучшить опыт для тех, кто использует медленные сети.

Когда сайты адаптируются к информации, которую предоставляют клиентские подсказки, нам не нужно принимать подход «все или ничего». Мы можем разумно решать, какие ресурсы отправлять. Мы можем изменить нашу адаптивную логику выбора изображений, чтобы отправлять изображения более низкого качества для данного дисплея, чтобы ускорить загрузку при плохом качестве сети.
В этом примере мы можем увидеть влияние клиентских подсказок на улучшение производительности сайтов в медленных сетях. Ниже представлен каскад WebPagetest сайта в медленной сети, который не адаптируется к клиентским подсказкам:

А теперь водопад для того же сайта при том же медленном соединении, за исключением того, что на этот раз сайт использует клиентские подсказки для исключения некритических ресурсов страницы:

Клиентские подсказки сократили время загрузки страницы с более чем 45 секунд до менее одной десятой этого времени . Преимущества клиентских подсказок в этом сценарии невозможно переоценить, и они могут стать серьезным благом для пользователей, ищущих важную информацию по медленным сетям.
Более того, можно использовать клиентские подсказки, не нарушая работу браузеров, которые их не поддерживают. Например, если мы хотим настроить доставку ресурсов, используя значение подсказки ECT
, при этом по-прежнему предоставляя полный опыт для неподдерживающих браузеров, мы можем установить откат к значению по умолчанию следующим образом:
// Set the ECT value to "4g" by default.
$ect = isset($_SERVER["HTTP_ECT"]) ? $_SERVER["HTTP_ECT"] : "4g";
Здесь "4g"
представляет сетевое соединение наивысшего качества, описанное заголовком ECT
. Если мы инициализируем $ect
в "4g"
, браузеры, не поддерживающие клиентские подсказки, не будут затронуты. Подпишитесь, FTW!
Осторожно, тайники!
Всякий раз, когда вы изменяете ответ на основе заголовка HTTP, вам нужно знать, как кэши будут обрабатывать будущие выборки для этого ресурса. Заголовок Vary
здесь незаменим, так как он связывает записи кэша со значением заголовков запроса, предоставленных ему. Проще говоря, если вы изменяете любой ответ на основе данного заголовка HTTP-запроса, вам почти всегда следует включать запрос этого заголовка в Vary
следующим образом:
Vary: DPR, Width
Однако есть одно важное предостережение: вы никогда не захотите Vary
кэшируемые ответы на часто меняющемся заголовке (например, Cookie
), потому что эти ресурсы становятся фактически некэшируемыми. Зная это, вы можете избегать Vary
на клиентских заголовках подсказок, таких как RTT
или Downlink
, потому что это факторы соединения, которые могут меняться довольно часто. Если вы хотите изменять ответы на эти заголовки, рассмотрите возможность изменения только заголовка ECT
, что сведет к минимуму промахи кэша.
Конечно, это применимо только в том случае, если вы кэшируете ответ в первую очередь. Например, вы не будете кэшировать HTML-активы, если их содержимое является динамическим, поскольку это может нарушить пользовательский опыт при повторных посещениях. В таких случаях не стесняйтесь изменять такие ответы на любой основе, которую вы считаете необходимой, и не беспокойтесь о Vary
.
Клиент намекает работникам сферы услуг
Согласование контента теперь не только для серверов! Поскольку сервис-воркеры действуют как прокси между клиентами и серверами, вы можете контролировать, как ресурсы доставляются через JavaScript. Это включает в себя клиентские подсказки. В событии fetch
сервис-воркера вы можете использовать метод request.headers.get
объекта event
, чтобы прочитать заголовки запроса ресурса, например:
self.addEventListener('fetch', (event) => {
let dpr = event.request.headers.get('DPR');
let viewportWidth = event.request.headers.get('Viewport-Width');
let width = event.request.headers.get('Width');
event.respondWith(
(async function () {
// Do what you will with these hints!
})(),
);
});
Любой заголовок клиентской подсказки, который вы выберете, может быть прочитан таким образом. Хотя это не единственный способ получить часть этой информации. Специфичные для сети подсказки могут быть прочитаны в этих эквивалентных свойствах JavaScript в объекте navigator
:
Подсказка клиенту | JS-эквивалент |
---|---|
`ЕСТ` | `navigator.connection.effectiveType` |
`РТТ` | `навигатор.подключение.rtt` |
`Сохранить-Данные` | `navigator.connection.saveData` |
`Нисходящая линия` | `навигатор.соединение.нисходящая.линк` |
`Устройство-Память` | `navigator.deviceMemory` |
Поскольку эти API доступны не везде, вам необходимо проверить функции с помощью оператора in
:
if ('connection' in navigator) {
// Work with netinfo API properties in JavaScript!
}
Отсюда вы можете использовать логику, похожую на ту, что вы использовали бы на сервере, за исключением того, что вам не нужен сервер для согласования контента с клиентскими подсказками. Только работники сервисов имеют возможность сделать опыт более быстрым и устойчивым благодаря дополнительной возможности обслуживать контент, когда пользователь находится в автономном режиме.
Подведение итогов
С помощью клиентских подсказок у нас есть возможность сделать опыт пользователей быстрее в полностью прогрессивном режиме. Мы можем обслуживать медиа на основе возможностей устройства пользователя таким образом, что обслуживание адаптивных изображений становится проще, чем при использовании <picture>
и srcset
, особенно для сложных случаев использования. Это позволяет нам не только сократить время и усилия на стороне разработки, но и оптимизировать ресурсы — в частности, изображения — таким образом, чтобы они точнее нацеливались на экраны пользователей, чем
Возможно, что еще важнее, мы можем вынюхивать плохие сетевые соединения и ликвидировать разрыв для пользователей, изменяя то, что мы отправляем, и то, как мы это отправляем. Это может иметь большое значение для облегчения доступа к сайтам для пользователей в хрупких сетях. В сочетании с работниками служб мы можем создавать невероятно быстрые сайты, доступные офлайн.
Хотя клиентские подсказки доступны только в Chrome и браузерах на основе Chromium, их можно использовать таким образом, чтобы не обременять браузеры, которые их не поддерживают. Рассмотрите возможность использования клиентских подсказок для создания действительно инклюзивного и адаптивного опыта, который учитывает возможности каждого устройства пользователя и сети, к которым он подключается. Будем надеяться, что другие поставщики браузеров оценят их ценность и проявят намерение внедрить.
Ресурсы
- Автоматические адаптивные изображения с подсказками для клиента
- Подсказки для клиентов и адаптивные изображения — что изменилось в Chrome 67
- Примите подсказку (клиента)! ( Слайды )
- Доставка быстрых и легких приложений с помощью
Save-Data
Благодарим Илью Григорика , Эрика Портиса , Джеффа Посника , Йоава Вайса и Эстель Вейл за их ценные отзывы и редактирование этой статьи.