Создание эффективного компонента изображения

Компонент изображения воплощает в себе лучшие практики производительности и предоставляет готовое решение для оптимизации изображений.

Лина Сохони
Leena Sohoni
Кара Эриксон
Kara Erickson
Алекс Кастл
Alex Castle

Изображения являются распространенным источником проблем с производительностью веб-приложений и ключевым направлением оптимизации. Неоптимизированные изображения способствуют раздуванию страницы и составляют более 70% общего веса страницы в байтах в 90 процентиле. Множество способов оптимизации изображений требуют интеллектуального «компонента изображения» с решениями по повышению производительности, встроенными по умолчанию.

Команда Aurora работала с Next.js над созданием одного такого компонента . Целью было создать оптимизированный шаблон изображения, который веб-разработчики могли бы дополнительно настраивать. Компонент служит хорошей моделью и устанавливает стандарт для создания компонентов изображения в других платформах, системах управления контентом (CMS) и стеках технологий. Мы сотрудничали над аналогичным компонентом для Nuxt.js и работаем с Angular над оптимизацией изображений в будущих версиях. В этом посте рассказывается о том, как мы разработали компонент изображения Next.js, и об уроках, которые мы извлекли на этом пути.

Компонент изображения как расширение изображений

Проблемы и возможности оптимизации изображений

Изображения влияют не только на производительность, но и на бизнес. Количество изображений на странице было вторым по значимости показателем конверсии пользователей, посещающих веб-сайты. В сеансах, в которых пользователи совершили конверсию, было на 38 % меньше изображений, чем в сеансах, в которых они не совершили конверсию. Lighthouse перечисляет множество возможностей для оптимизации изображений и улучшения веб-показателей в рамках своего аудита передового опыта. Ниже приведены некоторые из распространенных областей, в которых изображения могут влиять на основные веб-показатели и взаимодействие с пользователем.

Неразмерные изображения вредят CLS

Изображения, отображаемые без указания их размера, могут вызвать нестабильность макета и привести к большому совокупному сдвигу макета ( CLS ). Установка атрибутов width и height для элементов img может помочь предотвратить сдвиги макета. Например:

<img src="flower.jpg" width="360" height="240">

Ширина и высота должны быть установлены так, чтобы соотношение сторон визуализированного изображения было близко к его естественному соотношению сторон. Значительная разница в соотношении сторон может привести к искажению изображения. Относительно новое свойство, которое позволяет указать соотношение сторон в CSS, может помочь оперативно изменять размер изображений, предотвращая при этом CLS.

Большие изображения могут повредить LCP

Чем больше размер файла изображения, тем больше времени займет его загрузка. Большое изображение может быть «главным» изображением страницы или наиболее значимым элементом в области просмотра, ответственным за запуск отрисовки наибольшего содержимого ( LCP ). Изображение, которое является частью критического содержимого и загрузка которого занимает много времени, приведет к задержке LCP.

Во многих случаях разработчики могут уменьшить размеры изображений за счет лучшего сжатия и использования адаптивных изображений. Атрибуты srcset и sizes элемента <img> помогают предоставлять файлы изображений разных размеров. Затем браузер может выбрать правильный вариант в зависимости от размера и разрешения экрана.

Плохое сжатие изображений может повредить LCP

Современные форматы изображений, такие как AVIF или WebP, могут обеспечить лучшее сжатие, чем обычно используемые форматы JPEG и PNG. Лучшее сжатие уменьшает размер файла на 25–50 % в некоторых случаях при том же качестве изображения. Это сокращение приводит к более быстрой загрузке с меньшим потреблением данных. Приложение должно предоставлять современные форматы изображений браузерам, поддерживающим эти форматы.

Загрузка ненужных изображений вредит LCP

Изображения ниже сгиба или вне области просмотра не отображаются пользователю при загрузке страницы. Их можно отложить, чтобы они не вносили вклад в LCP и не задерживали его. Отложенную загрузку можно использовать для загрузки таких изображений позже, когда пользователь прокручивает их.

Проблемы оптимизации

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

  • Приоритеты : веб-разработчики обычно сосредотачиваются на коде, JavaScript и оптимизации данных. Таким образом, они могут не знать о проблемах с изображениями или о том, как их оптимизировать. Изображения, созданные дизайнерами или загруженные пользователями, могут не занимать первое место в списке приоритетов.
  • Готовое решение . Даже если разработчики осведомлены о нюансах оптимизации изображений, отсутствие универсального готового решения для их фреймворка или технологического стека может стать сдерживающим фактором.
  • Динамические изображения . Помимо статических изображений, которые являются частью приложения, пользователи загружают динамические изображения или получают их из внешних баз данных или CMS. Может быть сложно определить размер таких изображений, если источник изображения является динамическим.
  • Перегрузка разметки . Решения по включению размера изображения или srcset для разных размеров требуют дополнительной разметки для каждого изображения, что может быть утомительно. Атрибут srcset был введен в 2014 году, но сегодня используется только 26,5% веб-сайтов. При использовании srcset разработчикам приходится создавать изображения разных размеров. Такие инструменты, как just-gimme-an-img, могут помочь, но их придется использовать вручную для каждого изображения.
  • Поддержка браузера . Современные форматы изображений, такие как AVIF и WebP, создают файлы изображений меньшего размера, но требуют специальной обработки в браузерах, которые их не поддерживают. Разработчикам приходится использовать такие стратегии, как согласование контента или элемент <picture , чтобы изображения доставлялись всем браузерам.
  • Сложности с отложенной загрузкой . Существует множество методов и библиотек для реализации отложенной загрузки изображений, расположенных ниже сгиба. Выбор лучшего может оказаться непростой задачей. Разработчики также могут не знать оптимальное расстояние от «сгиба» для загрузки отложенных изображений. Различные размеры области просмотра на устройствах могут еще больше усложнить эту задачу.
  • Изменение ландшафта . Поскольку браузеры начинают поддерживать новые функции HTML или CSS для повышения производительности, разработчикам может быть сложно оценить каждую из них. Например, Chrome представляет функцию «Приоритет выборки» в качестве пробной версии Origin . Его можно использовать для повышения приоритета определенных изображений на странице. В целом, разработчикам было бы проще, если бы такие улучшения оценивались и реализовывались на уровне компонентов.

Имиджевый компонент как решение

Доступные возможности оптимизации изображений и трудности их реализации индивидуально для каждого приложения привели нас к идее компонента изображения. Компонент изображения может инкапсулировать и применять лучшие практики. Заменив элемент <img> компонентом изображения, разработчики смогут лучше решить проблемы с производительностью изображений.

В течение прошлого года мы работали с инфраструктурой Next.js над разработкой и реализацией их компонента Image . Его можно использовать в качестве замены существующих элементов <img> в приложениях Next.js следующим образом.

// Before with <img> element:
function Logo() {
  return <img src="/logo.jpg" alt="logo" height="200" width="100" />
}

// After with image component:
import Image from 'next/image'

function Logo() {
  return <Image src="/logo.jpg" alt="logo" height="200" width="100" />
}

Компонент пытается решить проблемы, связанные с изображениями, в целом, используя богатый набор функций и принципов. Он также включает параметры, которые позволяют разработчикам настраивать его в соответствии с различными требованиями к изображениям.

Защита от сдвигов планировки

Как обсуждалось ранее, изображения без размера вызывают изменения макета и способствуют CLS. При использовании компонента изображения Next.js разработчики должны указать размер изображения, используя атрибуты width и height , чтобы предотвратить любые сдвиги макета. Если размер неизвестен, разработчики должны указать layout=fill для предоставления изображения без размера, которое находится внутри контейнера определенного размера. В качестве альтернативы вы можете использовать импорт статических изображений, чтобы получить размер фактического изображения на жестком диске во время сборки и включить его в образ.

// Image component with width and height specified
<Image src="/logo.jpg" alt="logo" height="200" width="100" />

// Image component with layout specified
<Image src="/hero.jpg" layout="fill" objectFit="cover" alt="hero" />

// Image component with image import
import Image from 'next/image'
import logo from './logo.png'

function Logo() {
  return <Image src={logo} alt="logo" />
}

Поскольку разработчики не могут использовать компонент изображения без изменения размера, дизайн гарантирует, что они потратят время на рассмотрение размера изображения и предотвращение изменений макета.

Облегчение реагирования

Чтобы изображения реагировали на разные устройства, разработчики должны установить атрибуты srcset и sizes в элементе <img> . Мы хотели сократить эти усилия с помощью компонента «Изображение». Мы разработали компонент изображения Next.js так, чтобы значения атрибутов устанавливались только один раз для каждого приложения. Мы применяем их ко всем экземплярам компонента Image в зависимости от режима макета. Мы придумали решение, состоящее из трех частей:

  1. Свойство deviceSizes : это свойство можно использовать для однократной настройки точек останова на основе устройств, общих для базы пользователей приложения. Значения по умолчанию для точек останова включены в файл конфигурации.
  2. Свойство imageSizes : это также настраиваемое свойство, используемое для получения размеров изображения, соответствующих контрольным точкам размера устройства.
  3. Атрибут layout в каждом изображении: используется для указания того, как использовать свойства deviceSizes и imageSizes для каждого изображения. Поддерживаемые значения для режима макета: fixed , fill , intrinsic и responsive

Когда изображение запрашивается с режимами макета Response или Fill , Next.js идентифицирует изображение, которое будет обслуживаться, на основе размера устройства, запрашивающего страницу, и соответствующим образом устанавливает srcset и sizes изображения.

Следующее сравнение показывает, как режим макета можно использовать для управления размером изображения на разных экранах. Мы использовали демонстрационное изображение, опубликованное в документации Next.js, просмотренное на телефоне и стандартном ноутбуке.

Экран ноутбука Экран телефона
Макет = Внутренний: масштабируется до ширины контейнера на меньших окнах просмотра. Не масштабируется за пределы внутреннего размера изображения в большом окне просмотра. Ширина контейнера равна 100 %.
Изображение гор показано как естьИзображение гор уменьшено
Макет = Исправлено: изображение не реагирует. Ширина и высота фиксированы аналогично ` `элемент независимо от устройства, на котором он отображается.
Изображение гор показано как естьИзображение гор в том виде, в каком оно есть, не умещается на экране.
Макет = Адаптивный: масштабирование в зависимости от ширины контейнера в разных окнах просмотра с сохранением соотношения сторон.
Изображение гор увеличено до размера экранаИзображение гор уменьшено до размера экрана
Макет = Заливка: ширина и высота растягиваются для заполнения родительского контейнера. (В этом примере ширина родительского элемента <div> равна 300*500)
Изображение гор рендерится под размер 300*500.Изображение гор рендерится под размер 300*500.
Изображения, визуализированные для разных макетов

Обеспечьте встроенную отложенную загрузку

Компонент Image по умолчанию предоставляет встроенное высокопроизводительное решение для отложенной загрузки . При использовании элемента <img> есть несколько вариантов отложенной загрузки, но все они имеют недостатки, которые затрудняют их использование. Разработчик может использовать один из следующих подходов отложенной загрузки:

  • Укажите атрибут loading : поддерживается всеми современными браузерами .
  • Используйте API Intersection Observer . Создание собственного решения для отложенной загрузки требует усилий, а также продуманного проектирования и реализации. У разработчиков не всегда может быть на это время.
  • Импортируйте стороннюю библиотеку для отложенной загрузки изображений. Могут потребоваться дополнительные усилия для оценки и интеграции подходящей сторонней библиотеки для отложенной загрузки.

В компоненте изображения Next.js по умолчанию загрузка установлена ​​на "lazy" . Отложенная загрузка реализована с помощью Intersection Observer, который доступен в большинстве современных браузеров . Разработчикам не требуется делать ничего дополнительного, чтобы включить его, но они могут отключить его при необходимости.

Предварительная загрузка важных изображений

Довольно часто элементами LCP являются изображения, а большие изображения могут задерживать LCP. Рекомендуется предварительно загрузить важные изображения , чтобы браузер мог быстрее обнаружить их. При использовании элемента <img> подсказка о предварительной загрузке может быть включена в заголовок HTML следующим образом.

<link rel="preload" as="image" href="important.png">

Хорошо спроектированный компонент изображения должен предлагать возможность настройки последовательности загрузки изображений независимо от используемой платформы. В случае с компонентом изображения Next.js разработчики могут указать изображение, которое является подходящим кандидатом для предварительной загрузки, используя атрибут priority компонента изображений.

<Image src="/hero.jpg" alt="hero" height="400" width="200" priority />

Добавление атрибута priority упрощает разметку и делает ее более удобной в использовании. Разработчики компонентов изображений также могут изучить варианты применения эвристики для автоматизации предварительной загрузки изображений, расположенных над сгибом страницы, которые соответствуют определенным критериям.

Поощряйте высокопроизводительный хостинг изображений

CDN изображений рекомендуется для автоматизации оптимизации изображений, они также поддерживают современные форматы изображений, такие как WebP и AVIF. Компонент Next.js Image по умолчанию использует CDN изображений с использованием архитектуры загрузчика . В следующем примере показано, что загрузчик позволяет настраивать CDN в файле конфигурации Next.js.

module.exports = {
  images: {
    loader: 'imgix',
    path: 'https://ImgApp/imgix.net',
  },
}

При такой конфигурации разработчики могут использовать относительные URL-адреса в источнике изображения, а платформа объединит относительный URL-адрес с путем CDN для создания абсолютного URL-адреса. Поддерживаются популярные CDN изображений, такие как Imgix , Cloudinary и Akamai . Архитектура поддерживает использование специального облачного поставщика путем реализации специальной функции loader для приложения.

Поддержка самостоятельных изображений

Могут возникнуть ситуации, когда веб-сайты не могут использовать CDN изображений. В таких случаях компонент изображения должен поддерживать локальные изображения. Компонент Next.js Image использует оптимизатор изображений в качестве встроенного сервера изображений, который предоставляет CDN-подобный API. Оптимизатор использует Sharp для преобразования производственных изображений, если он установлен на сервере. Эта библиотека — хороший выбор для тех, кто хочет создать собственный конвейер оптимизации изображений.

Поддержка прогрессивной загрузки

Прогрессивная загрузка — это метод, используемый для поддержания интереса пользователей путем отображения изображения-заполнителя, обычно значительно более низкого качества, пока загружается фактическое изображение. Это улучшает воспринимаемую производительность и расширяет возможности пользователя. Его можно использовать в сочетании с отложенной загрузкой для изображений в нижней или верхней части сгиба.

Компонент Next.js Image поддерживает прогрессивную загрузку изображения через свойство заполнителя . Его можно использовать как LQIP (заполнитель изображения низкого качества) для отображения изображения низкого качества или размытия во время загрузки фактического изображения.

Влияние

Благодаря включению всех этих оптимизаций мы добились успеха в производстве компонента Next.js Image, а также работаем с другими технологическими стеками над аналогичными компонентами изображений.

Когда Leboncoin перенесла свой устаревший интерфейс JavaScript на Next.js , они также обновили свой конвейер изображений, чтобы использовать компонент изображения Next.js. На странице, которая перешла с <img> на next/image, время LCP снизилось с 2,4 до 1,7 с. Общий объем байтов изображений, загруженных для страницы, увеличился с 663 КБ до 326 КБ (примерно 100 КБ байтов изображений, загруженных с отложенной загрузкой).

Извлеченные уроки

Любой, кто создает приложение Next.js, может извлечь выгоду из использования компонента Next.js Image для оптимизации. Однако, если вы хотите создать аналогичные абстракции производительности для другой платформы или CMS, следующие уроки, которые мы извлекли на этом пути, могут оказаться полезными.

Предохранительные клапаны могут принести больше вреда, чем пользы

В ранней версии компонента изображения Next.js мы предоставили атрибут unsized , который позволял разработчикам обойти требования к размеру и использовать изображения с неуказанными размерами. Мы думали, что это будет необходимо в тех случаях, когда невозможно заранее узнать высоту или ширину изображения. Однако мы заметили, что пользователи рекомендуют атрибут unsized в проблемах GitHub как универсальное решение проблем с требованиями к размеру, даже в тех случаях, когда они могут решить проблему способами, не ухудшающими CLS. Впоследствии мы объявили устаревшим и удалили атрибут unsized .

Отделите полезное трение от бессмысленного раздражения

Требование к размеру изображения является примером «полезного трения». Это ограничивает использование компонента, но взамен обеспечивает огромный выигрыш в производительности. Пользователи с готовностью примут это ограничение, если у них будет четкое представление о потенциальных преимуществах производительности. Поэтому стоит объяснить этот компромисс в документации и других опубликованных материалах о компоненте.

Однако вы можете найти обходные пути для таких проблем, не жертвуя при этом производительностью. Например, во время разработки компонента Next.js Image мы получали жалобы на то, что раздражает поиск размеров локально хранящихся изображений. Мы добавили импорт статических изображений , который упрощает этот процесс за счет автоматического получения размеров локальных изображений во время сборки с помощью плагина Babel.

Найдите баланс между удобными функциями и оптимизацией производительности.

Если ваш компонент изображения не делает ничего, кроме навязывания «полезного трения» своим пользователям, разработчики, как правило, не захотят его использовать. Мы обнаружили, что, хотя функции производительности, такие как изменение размера изображения и автоматическое создание значений srcset , были наиболее важными. Удобные функции для разработчиков, такие как автоматическая отложенная загрузка и встроенные размытые заполнители, также вызвали интерес к компоненту Next.js Image.

Создайте дорожную карту для функций, способствующих внедрению

Создать решение, которое идеально работало бы во всех ситуациях, очень сложно. Может возникнуть соблазн разработать что-то, что будет хорошо работать для 75% людей, а затем сказать остальным 25%, что «в этих случаях этот компонент не для вас».

На практике оказывается, что эта стратегия противоречит вашим целям как разработчика компонентов. Вы хотите, чтобы разработчики внедрили ваш компонент, чтобы воспользоваться преимуществами его производительности. Это сложно сделать, если есть контингент пользователей, которые не могут мигрировать и чувствуют себя обделенными. Они, скорее всего, выразят разочарование, что приведет к негативному восприятию, которое повлияет на усыновление.

Желательно иметь план действий для вашего компонента, охватывающий все разумные варианты использования в долгосрочной перспективе. Это также помогает четко указать в документации, что не поддерживается и почему, чтобы сформулировать ожидания относительно проблем, которые компонент призван решить.

Заключение

Использование и оптимизация изображений сложны. Разработчикам приходится находить баланс между производительностью и качеством изображений, обеспечивая при этом удобство работы с пользователем. Это делает оптимизацию изображений дорогостоящим и высокоэффективным мероприятием.

Вместо того, чтобы каждое приложение каждый раз изобретало велосипед, мы разработали шаблон лучших практик, который разработчики, фреймворки и другие технические специалисты могли использовать в качестве эталона для своих собственных реализаций. Этот опыт действительно окажется ценным, поскольку мы поддерживаем другие фреймворки в их компонентах образа.

Компонент Next.js Image успешно улучшил производительность приложений Next.js, тем самым улучшив удобство работы с пользователем. Мы считаем, что это отличная модель, которая будет хорошо работать в более широкой экосистеме, и нам бы хотелось услышать мнение разработчиков, которые хотели бы использовать эту модель в своих проектах.

,

Компонент изображения воплощает в себе лучшие практики производительности и предоставляет готовое решение для оптимизации изображений.

Лина Сохони
Leena Sohoni
Кара Эриксон
Kara Erickson
Алекс Кастл
Alex Castle

Изображения являются распространенным источником проблем с производительностью веб-приложений и ключевым направлением оптимизации. Неоптимизированные изображения способствуют раздуванию страницы и составляют более 70% общего веса страницы в байтах в 90 процентиле. Множество способов оптимизации изображений требуют интеллектуального «компонента изображения» с решениями по повышению производительности, встроенными по умолчанию.

Команда Aurora работала с Next.js над созданием одного такого компонента . Целью было создать оптимизированный шаблон изображения, который веб-разработчики могли бы дополнительно настраивать. Компонент служит хорошей моделью и устанавливает стандарт для создания компонентов изображения в других платформах, системах управления контентом (CMS) и стеках технологий. Мы сотрудничали над аналогичным компонентом для Nuxt.js и работаем с Angular над оптимизацией изображений в будущих версиях. В этом посте рассказывается о том, как мы разработали компонент изображения Next.js, и об уроках, которые мы извлекли на этом пути.

Компонент изображения как расширение изображений

Проблемы и возможности оптимизации изображений

Изображения влияют не только на производительность, но и на бизнес. Количество изображений на странице было вторым по значимости показателем конверсии пользователей, посещающих веб-сайты. В сеансах, в которых пользователи совершили конверсию, было на 38 % меньше изображений, чем в сеансах, в которых они не совершили конверсию. Lighthouse перечисляет множество возможностей для оптимизации изображений и улучшения веб-показателей в рамках своего аудита передового опыта. Ниже приведены некоторые из распространенных областей, в которых изображения могут влиять на основные веб-показатели и взаимодействие с пользователем.

Неразмерные изображения вредят CLS

Изображения, отображаемые без указания их размера, могут вызвать нестабильность макета и привести к большому совокупному сдвигу макета ( CLS ). Установка атрибутов width и height для элементов img может помочь предотвратить сдвиги макета. Например:

<img src="flower.jpg" width="360" height="240">

Ширина и высота должны быть установлены так, чтобы соотношение сторон визуализированного изображения было близко к его естественному соотношению сторон. Значительная разница в соотношении сторон может привести к искажению изображения. Относительно новое свойство, которое позволяет указать соотношение сторон в CSS, может помочь оперативно изменять размер изображений, предотвращая при этом CLS.

Большие изображения могут повредить LCP

Чем больше размер файла изображения, тем больше времени займет его загрузка. Большое изображение может быть «главным» изображением страницы или наиболее значимым элементом в области просмотра, ответственным за запуск отрисовки наибольшего содержимого ( LCP ). Изображение, которое является частью критического содержимого и загрузка которого занимает много времени, приведет к задержке LCP.

Во многих случаях разработчики могут уменьшить размеры изображений за счет лучшего сжатия и использования адаптивных изображений. Атрибуты srcset и sizes элемента <img> помогают предоставлять файлы изображений разных размеров. Затем браузер может выбрать правильный вариант в зависимости от размера и разрешения экрана.

Плохое сжатие изображений может повредить LCP

Современные форматы изображений, такие как AVIF или WebP, могут обеспечить лучшее сжатие, чем обычно используемые форматы JPEG и PNG. Лучшее сжатие уменьшает размер файла на 25–50 % в некоторых случаях при том же качестве изображения. Это сокращение приводит к более быстрой загрузке с меньшим потреблением данных. Приложение должно предоставлять современные форматы изображений браузерам, поддерживающим эти форматы.

Загрузка ненужных изображений вредит LCP

Изображения ниже сгиба или вне области просмотра не отображаются пользователю при загрузке страницы. Их можно отложить, чтобы они не вносили вклад в LCP и не задерживали его. Отложенную загрузку можно использовать для загрузки таких изображений позже, когда пользователь прокручивает их.

Проблемы оптимизации

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

  • Приоритеты : веб-разработчики обычно сосредотачиваются на коде, JavaScript и оптимизации данных. Таким образом, они могут не знать о проблемах с изображениями или о том, как их оптимизировать. Изображения, созданные дизайнерами или загруженные пользователями, могут не занимать первое место в списке приоритетов.
  • Готовое решение . Даже если разработчики осведомлены о нюансах оптимизации изображений, отсутствие универсального готового решения для их фреймворка или технологического стека может стать сдерживающим фактором.
  • Динамические изображения . Помимо статических изображений, которые являются частью приложения, пользователи загружают динамические изображения или получают их из внешних баз данных или CMS. Может быть сложно определить размер таких изображений, если источник изображения является динамическим.
  • Перегрузка разметки . Решения по включению размера изображения или srcset для разных размеров требуют дополнительной разметки для каждого изображения, что может быть утомительно. Атрибут srcset был введен в 2014 году, но сегодня используется только 26,5% веб-сайтов. При использовании srcset разработчикам приходится создавать изображения разных размеров. Такие инструменты, как just-gimme-an-img, могут помочь, но их придется использовать вручную для каждого изображения.
  • Поддержка браузера . Современные форматы изображений, такие как AVIF и WebP, создают файлы изображений меньшего размера, но требуют специальной обработки в браузерах, которые их не поддерживают. Разработчикам приходится использовать такие стратегии, как согласование контента или элемент <picture , чтобы изображения доставлялись всем браузерам.
  • Сложности с отложенной загрузкой . Существует множество методов и библиотек для реализации отложенной загрузки изображений, расположенных ниже сгиба. Выбор лучшего может оказаться непростой задачей. Разработчики также могут не знать оптимальное расстояние от «сгиба» для загрузки отложенных изображений. Различные размеры области просмотра на устройствах могут еще больше усложнить эту задачу.
  • Изменение ландшафта . Поскольку браузеры начинают поддерживать новые функции HTML или CSS для повышения производительности, разработчикам может быть сложно оценить каждую из них. Например, Chrome представляет функцию «Приоритет выборки» в качестве пробной версии Origin . Его можно использовать для повышения приоритета определенных изображений на странице. В целом, разработчикам было бы проще, если бы такие улучшения оценивались и реализовывались на уровне компонентов.

Имиджевый компонент как решение

Доступные возможности оптимизации изображений и трудности их реализации индивидуально для каждого приложения привели нас к идее компонента изображения. Компонент изображения может инкапсулировать и применять лучшие практики. Заменив элемент <img> компонентом изображения, разработчики смогут лучше решить проблемы с производительностью изображений.

В течение прошлого года мы работали с инфраструктурой Next.js над разработкой и реализацией их компонента Image . Его можно использовать в качестве замены существующих элементов <img> в приложениях Next.js следующим образом.

// Before with <img> element:
function Logo() {
  return <img src="/logo.jpg" alt="logo" height="200" width="100" />
}

// After with image component:
import Image from 'next/image'

function Logo() {
  return <Image src="/logo.jpg" alt="logo" height="200" width="100" />
}

Компонент пытается решить проблемы, связанные с изображениями, в целом, используя богатый набор функций и принципов. Он также включает параметры, которые позволяют разработчикам настраивать его в соответствии с различными требованиями к изображениям.

Защита от сдвигов планировки

Как обсуждалось ранее, изображения без размера вызывают изменения макета и способствуют CLS. При использовании компонента изображения Next.js разработчики должны указать размер изображения, используя атрибуты width и height , чтобы предотвратить любые сдвиги макета. Если размер неизвестен, разработчики должны указать layout=fill для предоставления изображения без размера, которое находится внутри контейнера определенного размера. В качестве альтернативы вы можете использовать импорт статических изображений, чтобы получить размер фактического изображения на жестком диске во время сборки и включить его в образ.

// Image component with width and height specified
<Image src="/logo.jpg" alt="logo" height="200" width="100" />

// Image component with layout specified
<Image src="/hero.jpg" layout="fill" objectFit="cover" alt="hero" />

// Image component with image import
import Image from 'next/image'
import logo from './logo.png'

function Logo() {
  return <Image src={logo} alt="logo" />
}

Поскольку разработчики не могут использовать компонент изображения без изменения размера, дизайн гарантирует, что они потратят время на рассмотрение размера изображения и предотвращение изменений макета.

Облегчение реагирования

Чтобы изображения реагировали на разные устройства, разработчики должны установить атрибуты srcset и sizes в элементе <img> . Мы хотели сократить эти усилия с помощью компонента «Изображение». Мы разработали компонент изображения Next.js так, чтобы значения атрибутов устанавливались только один раз для каждого приложения. Мы применяем их ко всем экземплярам компонента Image в зависимости от режима макета. Мы придумали решение, состоящее из трех частей:

  1. Свойство deviceSizes : это свойство можно использовать для однократной настройки точек останова на основе устройств, общих для базы пользователей приложения. Значения по умолчанию для точек останова включены в файл конфигурации.
  2. Свойство imageSizes : это также настраиваемое свойство, используемое для получения размеров изображения, соответствующих контрольным точкам размера устройства.
  3. Атрибут layout в каждом изображении: используется для указания того, как использовать свойства deviceSizes и imageSizes для каждого изображения. Поддерживаемые значения для режима макета: fixed , fill , intrinsic и responsive

Когда изображение запрашивается с режимами макета «отзывчивый» или «заливка» , Next.js идентифицирует изображение, которое будет обслуживаться, на основе размера устройства, запрашивающего страницу, и соответствующим образом устанавливает srcset и sizes изображения.

Следующее сравнение показывает, как режим макета можно использовать для управления размером изображения на разных экранах. Мы использовали демонстрационное изображение, опубликованное в документации Next.js, просмотренное на телефоне и стандартном ноутбуке.

Экран ноутбука Экран телефона
Макет = Внутренний: масштабируется до ширины контейнера на меньших окнах просмотра. Не масштабируется за пределы внутреннего размера изображения в большом окне просмотра. Ширина контейнера равна 100 %.
Изображение гор показано как естьИзображение гор уменьшено
Макет = Исправлено: изображение не реагирует. Ширина и высота фиксированы аналогично ` `элемент независимо от устройства, на котором он отображается.
Изображение гор показано как естьИзображение гор в том виде, в каком оно есть, не умещается на экране.
Макет = Адаптивный: масштабирование в зависимости от ширины контейнера в разных окнах просмотра с сохранением соотношения сторон.
Изображение гор увеличено до размера экранаИзображение гор уменьшено до размера экрана
Макет = Заливка: ширина и высота растягиваются для заполнения родительского контейнера. (В этом примере ширина родительского элемента <div> равна 300*500)
Изображение гор рендерится под размер 300*500.Изображение гор рендерится под размер 300*500.
Изображения, визуализированные для разных макетов

Обеспечьте встроенную отложенную загрузку

Компонент Image по умолчанию предоставляет встроенное высокопроизводительное решение для отложенной загрузки . При использовании элемента <img> есть несколько вариантов отложенной загрузки, но все они имеют недостатки, которые затрудняют их использование. Разработчик может использовать один из следующих подходов отложенной загрузки:

  • Укажите атрибут loading : поддерживается всеми современными браузерами .
  • Используйте API Intersection Observer . Создание собственного решения для отложенной загрузки требует усилий, а также продуманного проектирования и реализации. У разработчиков не всегда может быть на это время.
  • Импортируйте стороннюю библиотеку для отложенной загрузки изображений. Могут потребоваться дополнительные усилия для оценки и интеграции подходящей сторонней библиотеки для отложенной загрузки.

В компоненте изображения Next.js по умолчанию загрузка установлена ​​на "lazy" . Отложенная загрузка реализована с помощью Intersection Observer, который доступен в большинстве современных браузеров . Разработчикам не требуется делать ничего дополнительного, чтобы включить его, но они могут отключить его при необходимости.

Предварительная загрузка важных изображений

Довольно часто элементами LCP являются изображения, а большие изображения могут задерживать LCP. Рекомендуется предварительно загрузить важные изображения , чтобы браузер мог быстрее обнаружить их. При использовании элемента <img> подсказка о предварительной загрузке может быть включена в заголовок HTML следующим образом.

<link rel="preload" as="image" href="important.png">

Хорошо спроектированный компонент изображения должен предлагать возможность настройки последовательности загрузки изображений независимо от используемой платформы. В случае с компонентом изображения Next.js разработчики могут указать изображение, которое является подходящим кандидатом для предварительной загрузки, используя атрибут priority компонента изображений.

<Image src="/hero.jpg" alt="hero" height="400" width="200" priority />

Добавление атрибута priority упрощает разметку и делает ее более удобной в использовании. Разработчики компонентов изображений также могут изучить варианты применения эвристики для автоматизации предварительной загрузки изображений, расположенных над сгибом страницы, которые соответствуют определенным критериям.

Поощряйте высокопроизводительный хостинг изображений

CDN изображений рекомендуется для автоматизации оптимизации изображений, они также поддерживают современные форматы изображений, такие как WebP и AVIF. Компонент Next.js Image по умолчанию использует CDN изображений с использованием архитектуры загрузчика . В следующем примере показано, что загрузчик позволяет настраивать CDN в файле конфигурации Next.js.

module.exports = {
  images: {
    loader: 'imgix',
    path: 'https://ImgApp/imgix.net',
  },
}

При такой конфигурации разработчики могут использовать относительные URL-адреса в источнике изображения, а платформа объединит относительный URL-адрес с путем CDN для создания абсолютного URL-адреса. Поддерживаются популярные CDN изображений, такие как Imgix , Cloudinary и Akamai . Архитектура поддерживает использование специального облачного поставщика путем реализации специальной функции loader для приложения.

Поддержка самостоятельных изображений

Могут возникнуть ситуации, когда веб-сайты не могут использовать CDN изображений. В таких случаях компонент изображения должен поддерживать локальные изображения. Компонент Next.js Image использует оптимизатор изображений в качестве встроенного сервера изображений, который предоставляет CDN-подобный API. Оптимизатор использует Sharp для преобразования рабочих изображений, если он установлен на сервере. Эта библиотека — хороший выбор для тех, кто хочет создать собственный конвейер оптимизации изображений.

Поддержка прогрессивной загрузки

Прогрессивная нагрузка - это метод, используемый для удержания интереса пользователей путем отображения изображения заполнителя, обычно значительно более низкого качества, в то время как фактические нагрузки изображения. Это улучшает воспринимаемую производительность и улучшает пользовательский опыт. Его можно использовать в сочетании с ленивой загрузкой для изображений ниже размера или для изображений выше.

Следующая компонент изображения. Это можно использовать в качестве LQIP (низкокачественный заполнитель изображения) для отображения низкокачественного или размытого изображения, в то время как фактическое изображение загружается.

Влияние

Со всеми этими оптимизациями мы наблюдаем успех с компонентом изображения hearl.js в производстве, а также работаем с другими техническими стеками над аналогичными компонентами изображения.

Когда Leboncoin мигрировал свой Legacy JavaScript Frontend на next.js , они также обновили свой конвейер изображений, чтобы использовать компонент изображения healh.js. На странице, которая мигрировала с <img> на следующее/изображение, LCP снизился с 2,4 до 1,7. Общее изображение байты, загруженные для страницы, прошли с 663 КБ до 326 КБ (с ~ 100 КБ байтов с ленивым нагруженным изображением).

Уроки извлечены

Любой, кто создает приложение Next.js, может извлечь выгоду из использования компонента изображения Next.js для оптимизации. Однако, если вы хотите создать аналогичные абстракции производительности для другой структуры или CMS, ниже приведены несколько уроков, которые мы извлекли по пути, которые могут быть полезными.

Предохранительные клапаны могут нанести больший вред, чем пользы

В раннем выпуске компонента изображения Next.js мы предоставили unsized атрибут, который позволил разработчикам обходить требования по размеру и использовать изображения с неопределенными измерениями. Мы думали, что это будет необходимо в тех случаях, когда было невозможно заранее узнать высоту или ширину изображения. Тем не менее, мы заметили, что пользователи рекомендовали unsized атрибут в вопросах GitHub в качестве решения всех проблем с требованиями размеров, даже в тех случаях, когда они могли решить проблему таким образом, чтобы не ухудшиться CLS. Впоследствии мы устарели и удалили unsized атрибут.

Отдельное полезное трение от бессмысленного раздражения

Требование по размеру изображения является примером «полезного трения». Он ограничивает использование компонента, но обеспечивает огромные преимущества производительности в обмене. Пользователи с готовностью примут ограничение, если у них есть четкое представление о потенциальных преимуществах производительности. Поэтому стоит объяснить этот компромисс в документации и другие опубликованные материалы о компоненте.

Тем не менее, вы можете найти обходные пути для такого трения, не жертвуя производительностью. Например, во время разработки компонента Image Next.js мы получили жалобы на то, что это раздражало искать размеры для локально хранимых изображений. Мы добавили статический импорт изображений , который оптимизирует этот процесс, автоматически извлекая размеры для локальных изображений во время сборки с помощью плагина Babel.

Положите баланс между удобными функциями и оптимизацией производительности

Если ваш компонент изображения не делает ничего, кроме как навязывать «полезное трение» на своих пользователей, разработчики, как правило, не захотят его использовать. Мы обнаружили, что, хотя функции производительности, такие как размер изображения и автоматическая генерация значений srcset были наиболее важными. Удобные функции разработчиков, такие как автоматическая ленивая загрузка и встроенные размытые заполнители, также вызвали интерес к следующему компоненту изображения.

Установите дорожную карту для функций для управления принятием

Создание решения, которое отлично подходит для всех ситуаций, очень сложно. Может быть заманчиво спроектировать что -то, что хорошо работает для 75% людей, а затем сказать другим 25%, что «В этих случаях этот компонент не для вас».

На практике эта стратегия оказывается противоречивой с вашими целями в качестве дизайнера компонентов. Вы хотите, чтобы разработчики приняли ваш компонент, чтобы извлечь выгоду из его выгод. Это сложно сделать, если есть контингент пользователей, которые не могут мигрировать и чувствовать себя оставленными в нерабочее время. Они, вероятно, выражают разочарование, что приведет к негативному восприятию, которые влияют на усыновление.

Желательно иметь дорожную карту для вашего компонента, которая охватывает все разумные варианты использования в долгосрочной перспективе. Это также помогает быть явным в документации о том, что не поддерживается, и почему для того, чтобы установить ожидания относительно проблем, которые компонент предназначен для решения.

Заключение

Использование изображения и оптимизация сложны. Разработчики должны найти баланс между производительностью и качеством изображений, обеспечивая отличный пользовательский опыт. Это делает оптимизацию изображения дорогостоящим, высокоэффективным усилием.

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

Следующий компонент изображения. Мы считаем, что это отличная модель, которая будет хорошо работать в более широкой экосистеме, и мы хотели бы услышать от разработчиков, которые хотели бы принять эту модель в своих проектах.