Оптимизация изображений

Примеры

Согласно Web Almanac, изображения составляют значительную часть веса страницы типичного веб-сайта и могут существенно влиять на производительность LCP.

Компонент Next.js Image расширяет HTML-элемент <img>, добавляя функции автоматической оптимизации изображений:

  • Оптимизация размера: Автоматическая подача изображений правильного размера для каждого устройства с использованием современных форматов, таких как WebP и AVIF.
  • Визуальная стабильность: Автоматическое предотвращение сдвига макета при загрузке изображений.
  • Быстрая загрузка страниц: Изображения загружаются только при попадании в область видимости с использованием нативной ленивой загрузки браузера и опциональных размытых плейсхолдеров.
  • Гибкость работы с активами: Изменение размера изображений по требованию, даже для изображений на удаленных серверах.

🎥 Видео: Узнайте больше об использовании next/imageYouTube (9 минут).

Использование

import Image from 'next/image'

Затем вы можете определить src для вашего изображения (локального или удаленного).

Локальные изображения

Для использования локального изображения импортируйте файлы .jpg, .png или .webp.

Next.js автоматически определит width и height вашего изображения на основе импортированного файла. Эти значения используются для предотвращения кумулятивного сдвига макета во время загрузки изображения.

pages/index.js
import Image from 'next/image'
import profilePic from '../public/me.png'

export default function Page() {
  return (
    <Image
      src={profilePic}
      alt="Фотография автора"
      // width={500} предоставляется автоматически
      // height={500} предоставляется автоматически
      // blurDataURL="data:..." предоставляется автоматически
      // placeholder="blur" // Опциональный размытый плейсхолдер при загрузке
    />
  )
}

Предупреждение: Динамический await import() или require() не поддерживаются. Импорт должен быть статическим, чтобы его можно было проанализировать во время сборки.

Удаленные изображения

Для использования удаленного изображения свойство src должно быть строкой URL.

Поскольку Next.js не имеет доступа к удаленным файлам во время сборки, вам нужно вручную указать свойства width, height и опциональное blurDataURL.

Атрибуты width и height используются для определения правильного соотношения сторон изображения и предотвращения сдвига макета при загрузке. width и height не определяют размер отображаемого файла изображения. Подробнее о размерах изображений.

app/page.js
import Image from 'next/image'

export default function Page() {
  return (
    <Image
      src="https://s3.amazonaws.com/my-bucket/profile.png"
      alt="Фотография автора"
      width={500}
      height={500}
    />
  )
}

Для безопасной оптимизации изображений определите список поддерживаемых шаблонов URL в next.config.js. Будьте максимально конкретными, чтобы предотвратить злонамеренное использование. Например, следующая конфигурация разрешит только изображения из определенного бакета AWS S3:

next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 's3.amazonaws.com',
        port: '',
        pathname: '/my-bucket/**',
      },
    ],
  },
}

Узнайте больше о конфигурации remotePatterns. Если вы хотите использовать относительные URL для src изображения, используйте loader.

Домены

Иногда может потребоваться оптимизировать удаленное изображение, но при этом использовать встроенный API оптимизации изображений Next.js. Для этого оставьте loader со значением по умолчанию и укажите абсолютный URL для свойства src изображения.

Для защиты вашего приложения от злонамеренных пользователей необходимо определить список удаленных доменных имен, которые вы планируете использовать с компонентом next/image.

Узнайте больше о конфигурации remotePatterns.

Загрузчики

Обратите внимание, что в примере выше для локального изображения указан частичный URL ("/me.png"). Это возможно благодаря архитектуре загрузчиков.

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

Загрузчик по умолчанию для приложений Next.js использует встроенный API оптимизации изображений, который оптимизирует изображения из любого места в интернете и затем подает их напрямую с веб-сервера Next.js. Если вы хотите подавать изображения напрямую с CDN или сервера изображений, вы можете написать собственную функцию загрузчика несколькими строками JavaScript.

Вы можете определить загрузчик для каждого изображения с помощью свойства loader или на уровне приложения с помощью конфигурации loaderFile.

Приоритет

Свойство priority следует добавлять к изображению, которое будет элементом Largest Contentful Paint (LCP) для каждой страницы. Это позволяет Next.js специально приоритезировать загрузку изображения (например, через теги предзагрузки или подсказки приоритета), что значительно улучшает LCP.

Элемент LCP обычно является самым большим изображением или текстовым блоком, видимым в области просмотра страницы. При запуске next dev вы увидите предупреждение в консоли, если элемент LCP является <Image> без свойства priority.

Определив изображение LCP, вы можете добавить свойство следующим образом:

app/page.js
import Image from 'next/image'

export default function Home() {
  return (
    <>
      <h1>Моя домашняя страница</h1>
      <Image
        src="/me.png"
        alt="Фотография автора"
        width={500}
        height={500}
        priority
      />
      <p>Добро пожаловать на мою домашнюю страницу!</p>
    </>
  )
}

Подробнее о приоритете в документации компонента next/image.

Размеры изображений

Один из самых распространенных способов, которым изображения ухудшают производительность, — это сдвиг макета, когда изображение сдвигает другие элементы на странице во время загрузки. Эта проблема настолько раздражает пользователей, что для нее существует отдельный Core Web Vital под названием Cumulative Layout Shift. Способ избежать сдвигов макета из-за изображений — всегда указывать их размеры. Это позволяет браузеру заранее зарезервировать точное место для изображения.

Поскольку next/image разработан для гарантии хорошей производительности, он не может использоваться способом, который вызывает сдвиг макета, и должен быть размещен одним из трех способов:

  1. Автоматически, с использованием статического импорта
  2. Явно, путем указания свойств width и height
  3. Неявно, с использованием fill, что заставляет изображение заполнять родительский элемент.

Что делать, если я не знаю размеров изображения?

Если вы получаете изображения из источника, размеры которых неизвестны, есть несколько вариантов:

Используйте fill

Свойство fill позволяет изображению масштабироваться в соответствии с родительским элементом. Используйте CSS, чтобы задать пространство для родительского элемента, и свойство sizes для соответствия медиазапросам. Также можно использовать object-fit со значениями fill, contain или cover и object-position для определения позиционирования изображения.

Нормализуйте изображения

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

Измените API-запросы

Если ваше приложение получает URL изображений через API (например, CMS), можно модифицировать запрос, чтобы он возвращал размеры вместе с URL.

Если ни один из предложенных методов не подходит, компонент next/image хорошо работает на странице вместе с обычными элементами <img>.

Стилизация

Стилизация компонента Image похожа на стилизацию обычного <img>, но есть несколько рекомендаций:

  • Используйте className или style, а не styled-jsx.
    • В большинстве случаев рекомендуется использовать свойство className. Это может быть импортированный CSS Module, глобальная таблица стилей и т.д.
    • Также можно использовать свойство style для inline-стилей.
    • Нельзя использовать styled-jsx, так как он ограничен текущим компонентом (если только стиль не помечен как global).
  • При использовании fill родительский элемент должен иметь position: relative
    • Это необходимо для правильного отображения элемента изображения в этом режиме.
  • При использовании fill родительский элемент должен иметь display: block
    • Это значение по умолчанию для <div>, но его нужно указывать явно в других случаях.

Примеры

Адаптивность

Адаптивное изображение, заполняющее ширину и высоту родительского контейнера
import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Responsive() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      <Image
        alt="Горы"
        // Импорт изображения автоматически
        // устанавливает ширину и высоту
        src={mountains}
        sizes="100vw"
        // Растягиваем изображение на всю ширину
        style={{
          width: '100%',
          height: 'auto',
        }}
      />
    </div>
  )
}

Заполнение контейнера

Сетка изображений, заполняющих ширину родительского контейнера
import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Fill() {
  return (
    <div
      style={{
        display: 'grid',
        gridGap: '8px',
        gridTemplateColumns: 'repeat(auto-fit, minmax(400px, auto))',
      }}
    >
      <div style={{ position: 'relative', height: '400px' }}>
        <Image
          alt="Горы"
          src={mountains}
          fill
          sizes="(min-width: 808px) 50vw, 100vw"
          style={{
            objectFit: 'cover', // cover, contain, none
          }}
        />
      </div>
      {/* И другие изображения в сетке... */}
    </div>
  )
}

Фоновое изображение

Фоновое изображение, занимающее всю ширину и высоту страницы
import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Background() {
  return (
    <Image
      alt="Горы"
      src={mountains}
      placeholder="blur"
      quality={100}
      fill
      sizes="100vw"
      style={{
        objectFit: 'cover',
      }}
    />
  )
}

Другие примеры использования компонента Image с различными стилями можно найти в демонстрации компонента Image.

Другие свойства

Все доступные свойства компонента next/image.

Конфигурация

Компонент next/image и API оптимизации изображений Next.js можно настроить в файле next.config.js. Эти настройки позволяют разрешить удаленные изображения, определить пользовательские брейкпоинты, изменить поведение кэширования и многое другое.

Подробнее о настройке изображений.