Разработка сайтов, которые быстро загружаются везде, может быть непростой задачей. Многообразие возможностей устройств и качество сетей, к которым они подключаются, могут создать впечатление, что это непосильная задача. Хотя мы можем использовать функции браузера для улучшения скорости загрузки, как узнать, на что способно устройство пользователя или каково качество его сетевого соединения? Решение – подсказки от клиента !
Заголовки 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 ». Не беспокойтесь о самих конкретных подсказках. Мы рассмотрим их чуть позже.
Эти заголовки с возможностью включения можно установить в любом языке программирования. Например, можно использовать функцию header в PHP . Можно даже установить эти заголовки с возможностью включения с помощью атрибута 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 пикселей, скорректированным по плотности, но к нему также применены свойства width и height CSS со значениями 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 hint был включен, клиент отправит этот параметр Width на сервер вместе с запросом src элемента <img> :
Width: 544
В данном случае клиент сообщает серверу, что оптимальная внутренняя ширина для запрашиваемого изображения составит 85% от ширины области просмотра (272 пикселя), умноженной на DPR экрана (2), что равно 544 пикселям.
Эта подсказка особенно полезна, поскольку она учитывает не только скорректированную по плотности ширину экрана, но и согласовывает эту важную информацию с внешним размером изображения в рамках макета. Это дает серверам возможность согласовывать отклик изображения, оптимальный как для экрана , так и для макета.
Content-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, и они будут полностью сняты для всех платформ после завершения работы над политикой функций .
Помощь пользователям с медленными сетями.
Адаптивная производительность — это идея, согласно которой мы можем корректировать способ предоставления ресурсов на основе информации, предоставляемой нам подсказками клиента, а именно информации о текущем состоянии сетевого соединения пользователя.
Что касается сайта 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" , браузеры, не поддерживающие подсказки клиента, не будут затронуты. Включение этой функции — залог успеха!
Осторожно, тайники!
При изменении ответа на основе 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 :
| Подсказка для клиента | эквивалент на JavaScript |
|---|---|
| `ECT` | `navigator.connection.effectiveType` |
| `RTT` | `navigator.connection.rtt` |
| `Сохранить данные` | `navigator.connection.saveData` |
| `Ссылка для скачивания` | `navigator.connection.downlink` |
| `Устройство-Память` | `navigator.deviceMemory` |
Поскольку эти API доступны не везде, вам потребуется проверить наличие необходимых функций с помощью оператора in :
if ('connection' in navigator) {
// Work with netinfo API properties in JavaScript!
}
Отсюда вы можете использовать логику, аналогичную той, что применялась бы на сервере, за исключением того, что вам не нужен сервер для согласования контента с подсказками клиента. Сервис-воркеры сами по себе способны сделать работу с контентом быстрее и надежнее благодаря дополнительной возможности предоставлять контент, когда пользователь находится в автономном режиме.
Подводя итоги
Благодаря клиентским подсказкам мы можем ускорить взаимодействие с пользователями, используя полностью прогрессивный подход. Мы можем предоставлять медиаконтент в зависимости от возможностей устройства пользователя, что упрощает показ адаптивных изображений по сравнению с использованием тегов <picture> и srcset , особенно в сложных сценариях использования. Это позволяет нам не только сократить время и усилия на этапе разработки, но и оптимизировать ресурсы, особенно изображения, более точно адаптируя их к экранам пользователей.
Что, пожалуй, еще важнее, мы можем выявлять слабые сетевые соединения и устранять их, изменяя передаваемые данные и способ их отправки. Это может значительно упростить доступ к сайтам для пользователей в сетях с нестабильной связью. В сочетании с сервисными работниками мы можем создавать невероятно быстрые сайты, доступные в офлайн-режиме.
Хотя подсказки для клиента доступны только в Chrome и браузерах на основе Chromium, их можно использовать таким образом, чтобы не создавать проблем для браузеров, которые их не поддерживают. Рассмотрите возможность использования подсказок для клиента для создания действительно инклюзивных и адаптируемых интерфейсов, учитывающих возможности устройства каждого пользователя и сети, к которым он подключается. Будем надеяться, что другие производители браузеров оценят их преимущества и проявят намерение внедрить их.
Ресурсы
- Автоматически адаптируемые изображения с подсказками для клиента
- Подсказки для пользователей и адаптивные изображения — что изменилось в Chrome 67.
- Учтите подсказку (для клиента)! ( Слайды )
- Создание быстрых и легковесных приложений с помощью
Save-Data
Благодарим Илью Григорика , Эрика Портиса , Джеффа Посника , Йоава Вайсса и Эстель Вейль за ценные замечания и правки к этой статье.