8 lines
18 KiB
JSON
8 lines
18 KiB
JSON
{
|
||
"index": 193,
|
||
"slug": "editorial-2022-08-field-media-performance",
|
||
"title": "Когда маленькая картинка тормозит страницу: как найти причину в media-слоте",
|
||
"excerpt": "Изображение может быть маленьким на экране и большим в сети. Разбираем source mapping, геометрию, priority и безопасную проверку одной обратимой правки.",
|
||
"contentHtml": "<p>Карточка товара занимает большую часть сетевого бюджета, хотя её изображение на экране имеет ширину всего 320 пикселей. Hero появляется поздно. При загрузке фильтра соседний текст прыгает вниз. В отчёте кто-то пишет: «картинка тормозит страницу» — и предлагает добавить priority или заменить файл.</p>\n<p>Такой диагноз слишком широк. Ошибка может находиться в исходнике, в расчёте размера слота, в разметке, в CSS или в составе первого экрана. Если поменять CDN-вариант, размеры и атрибуты сразу, команда потеряет связь между причиной и результатом. Цена ошибки — лишний трафик, поздний полезный контент и релиз, который невозможно уверенно откатить.</p>\n<p><strong>Тезис:</strong> медиа оптимизируют не по размеру файла и не по одному атрибуту. Сначала нужно описать конкретный слот, затем проверить его геометрию и выбор ресурса, после этого сопоставить намерение приложения с фактическим браузерным наблюдением. Одна гипотеза требует одной обратимой правки и повторного прогона в тех же условиях.</p>\n<h2>Механизм: один слот, несколько независимых решений</h2>\n<p>Media-слот — это не только URL картинки. У него есть содержимое, ожидаемый размер, вариант кадрирования, плотность экрана, момент появления и место в композиции страницы. Эти решения связаны, но не заменяют друг друга.</p>\n<p>Сначала браузер получает HTML и видит элемент <code>img</code>. Атрибуты <code>srcset</code> и <code>sizes</code> дают ему набор кандидатов и ожидаемую ширину слота. Браузер сопоставляет эту подсказку с viewport и плотностью экрана, а затем выбирает ресурс. Если <code>sizes</code> описывает слот как 960 пикселей, хотя фактическая колонка занимает 320, браузер может выбрать слишком крупный кандидат. Малый видимый результат не означает малый сетевой расход.</p>\n<p>Геометрия решает другую задачу. Атрибуты <code>width</code> и <code>height</code> задают intrinsic ratio изображения. Когда браузер знает соотношение сторон до загрузки, он может заранее зарезервировать место. Это снижает риск скачка соседнего контента. Но наличие атрибутов не доказывает отсутствие layout shift: контейнер, CSS, шрифт и ветка состояния могут изменить фактический layout.</p>\n<p>Приоритет загрузки тоже имеет две стороны. Код или фреймворк может считать hero критичным и передать это намерение загрузочному пути. Это не равно доказанному порядку сетевых запросов или paint. На порядок влияют разметка, другие ресурсы, браузер, кеш и состояние страницы. Поэтому строка конфигурации — гипотеза о намерении, а trace или performance-запись — наблюдение в конкретных условиях.</p>\n<h2>Пример: описать слот до изменения страницы</h2>\n<p>Ниже — учебный пример разметки. Он показывает контракт компонента: слот имеет размеры, набор кандидатов и текст для доступности. Пример не открывает страницу, не загружает файл и не измеряет LCP или CLS.</p>\n<pre><code><img\n src=\"/media/product-640.avif\"\n srcset=\"/media/product-320.avif 320w,\n /media/product-640.avif 640w,\n /media/product-960.avif 960w\"\n sizes=\"(max-width: 600px) 320px, 640px\"\n width=\"640\"\n height=\"480\"\n alt=\"Чёрный рюкзак на белом фоне\"\n/></code></pre>\n<p>В этом примере <code>sizes</code> должен соответствовать реальной ширине слота, а не желаемому размеру самого большого кандидата. Если карточка на узком экране занимает 320 CSS-пикселей, это нужно проверить через фактический layout. Если мобильная композиция показывает другой фрагмент изображения, одного <code>srcset</code> недостаточно: понадобится art direction через <code>picture</code> и отдельные <code>source</code>.</p>\n<p>Нельзя объявлять учебный объект доказательством загрузки. Проверка вроде «в данных есть <code>loaded</code>» говорит только о состоянии модели. Она не подтверждает, что браузер получил response, декодировал изображение и нарисовал его. Для этого нужен отдельный прогон страницы и зафиксированные условия.</p>\n<h2>Симптомы, причины и действия</h2>\n<div class=\"table-scroll\"><table><caption>Диагностика одного media-слота</caption><thead><tr><th scope=\"col\">Симптом</th><th scope=\"col\">Возможная причина</th><th scope=\"col\">Проверка</th><th scope=\"col\">Действие</th></tr></thead><tbody><tr><td>Маленькая картинка скачивает большой файл</td><td>Неверный <code>sizes</code>, отсутствует подходящий кандидат или CDN всегда отдаёт desktop-вариант</td><td>Сравнить rendered width, выбранный URL, response size и значения <code>srcset</code>/<code>sizes</code></td><td>Исправить mapping или подсказку размера; повторить тот же viewport</td></tr><tr><td>Контент прыгает после загрузки</td><td>Нет известного ratio, контейнер меняет размер или CSS переопределяет рамку</td><td>Проверить DOM и computed layout до и после загрузки в одном сценарии</td><td>Задать корректные размеры или ratio; проверить фактический layout</td></tr><tr><td>Hero появляется поздно</td><td>Ресурс конкурирует с другими запросами, находится далеко в разметке или выбран слишком тяжёлый вариант</td><td>Снять trace с route, viewport, кешем и браузером; найти request и paint-события</td><td>Изменить только один слой: source, композицию или загрузочный путь</td></tr><tr><td>Метка priority не дала ожидаемого эффекта</td><td>Намерение приложения приняли за гарантию планировщика браузера</td><td>Разделить config intent и фактический порядок запросов в trace</td><td>Оставить наблюдаемый результат, проверить конкурирующие ресурсы и не добавлять второй флаг без гипотезы</td></tr><tr><td>Изображение стало резким, но объект обрезан</td><td>Поменяли resolution switching вместо art direction</td><td>Сравнить crop на целевом viewport и описание содержимого в alt</td><td>Использовать отдельный источник для композиции, сохранив fallback</td></tr></tbody></table></div>\n<h2>Иллюстрация границы диагностики</h2>\n<figure><img src=\"/assets/editorial/2022/media-performance-2022-diagnosis-rollback.svg\" alt=\"Диагностическая схема media-слота: симптом разделяется на проблемы источника, геометрии и приоритета, после чего выполняется одна обратимая правка и повторный браузерный прогон\" loading=\"lazy\" /><figcaption>Один симптом может иметь разные причины. Сначала выбирается слой проверки, затем меняется один параметр. Если наблюдение не подтвердило гипотезу, возвращается прежнее значение.</figcaption></figure>\n<p>Схема полезна как ограничитель области. Поздний hero нельзя автоматически объяснить отсутствием размеров. Скачок layout нельзя исправить только сменой формата. Большой response нельзя объявить проблемой priority, пока не проверены кандидат и фактическая ширина слота.</p>\n<h2>Порядок действий</h2>\n<ol><li><strong>Зафиксируйте симптом.</strong> Запишите один URL, один media-слот, viewport, браузер, состояние кеша и наблюдаемое событие. Формулировка «страница медленная» не подходит.</li><li><strong>Опишите контракт.</strong> Укажите содержимое, <code>src</code>, кандидаты <code>srcset</code>, <code>sizes</code>, размеры, alt, предполагаемый crop и намерение critical или deferred. Называйте намерение именно намерением.</li><li><strong>Проверьте данные и разметку.</strong> Убедитесь, что ширина и высота положительны, ratio соответствует изображению, fallback существует, а alt описывает изображение, а не имя файла.</li><li><strong>Проверьте браузерный слой.</strong> Откройте тот же сценарий и сравните фактический rendered width, выбранный ресурс, response, порядок запросов и момент появления. Учебная fixture не заменяет этот шаг.</li><li><strong>Выберите одну гипотезу.</strong> Например: «на ширине 320 пикселей выбирается кандидат 960w из-за неверного <code>sizes</code>». Не объединяйте её с изменением CSS и priority.</li><li><strong>Внесите обратимую правку.</strong> Сохраните прежний source mapping или значение атрибута. Не удаляйте evidence: старое наблюдение нужно для сравнения и отката.</li><li><strong>Повторите прогон.</strong> Используйте те же route, viewport, браузер и cache state. Если гипотеза не подтвердилась, откатите правку и расширьте проверку, а не наслаивайте следующую оптимизацию.</li></ol>\n<h2>Ограничения и отрицательный путь</h2>\n<p>Размеры изображения помогают резервировать место, но не исправляют layout, который меняется из-за шрифта, рекламы, пользовательского состояния или позднего CSS. <code>srcset</code> и <code>sizes</code> уменьшают лишний download только при корректном описании слота и доступных кандидатах. <code>picture</code> решает art direction, но добавляет варианты, которые нужно проверить на содержимое и fallback.</p>\n<p>Не делайте вывод о LCP по времени ответа картинки. LCP — это наблюдение о крупнейшем отрисованном элементе в конкретной загрузке. Запрос мог завершиться раньше paint, а другой элемент мог стать кандидатом. Датированный First Public Working Draft W3C от 24 мая 2022 года описывает API и его ограничения, но не гарантирует результат конкретной страницы.</p>\n<p>Если trace не подтверждает гипотезу, отрицательный путь имеет конкретный вид: вернуть прежнее значение, сохранить условия прогона, отметить гипотезу как неподтверждённую и выбрать следующий слой. Если картинка всё ещё поздняя после уменьшения ресурса, проверяйте композицию страницы и конкурирующие запросы. Если скачок остаётся после добавления размеров, проверяйте реальный контейнер и CSS. Если source стал меньше, но crop ухудшился, откатите source mapping и решайте задачу art direction.</p>\n<h2>Проверяемый критерий готовности</h2>\n<p>Разбор готов, когда для одного слота сохранены четыре вещи: воспроизводимый симптом с условиями; проверенная причина или явно отвергнутая гипотеза; одна правка с понятным откатом; повторный результат в том же сценарии. Для source должны быть видны выбранный URL и размер response. Для геометрии — фактическая рамка до и после загрузки. Для priority — разделённые intent и browser observation.</p>\n<p>Не называйте работу завершённой по формулировке «стало быстрее» и не добавляйте выдуманный процент. Учебный HTML подтверждает только структуру примера. Production-вывод требует реальной страницы, реального браузерного прогона и сохранённого артефакта наблюдения. Такой критерий не обещает, что медиа больше никогда не станет проблемой. Он делает следующую ошибку обнаружимой и позволяет откатить спорную правку.</p>\n<h2>Проверяемые источники</h2><ul><li><a href=\"https://www.w3.org/TR/2022/WD-largest-contentful-paint-20220524/\" target=\"_blank\" rel=\"noopener noreferrer\">W3C: Largest Contentful Paint, First Public Working Draft от 24 мая 2022 года</a> — датированная рабочая версия. Она описывает API и его ограничения, но не гарантирует поведение конкретной страницы.</li><li><a href=\"https://www.w3.org/TR/2017/REC-html52-20171214/semantics-embedded-content.html#the-img-element\" target=\"_blank\" rel=\"noopener noreferrer\">W3C: HTML 5.2 — элемент img</a> — стабильная нормативная версия с правилами для элемента изображения и его атрибутов.</li><li><a href=\"https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images\" target=\"_blank\" rel=\"noopener noreferrer\">MDN: Responsive images</a> — практическая документация по <code>srcset</code>, <code>sizes</code> и art direction через <code>picture</code>.</li></ul>"
|
||
}
|