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

Примеры

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

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

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

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

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

import Image from 'next/image'

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

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

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

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

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() не поддерживаются. Импорт должен быть статическим, чтобы его можно было проанализировать во время сборки.

Вы можете опционально настроить localPatterns в файле next.config.js, чтобы разрешить определённые изображения и заблокировать все остальные.

next.config.js
module.exports = {
  images: {
    localPatterns: [
      {
        pathname: '/assets/images/**',
        search: '',
      },
    ],
  },
}

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

Для использования удалённого изображения свойство 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/**',
        search: '',
      },
    ],
  },
}

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

Домены

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

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

Узнайте больше о настройке remotePatterns.

Загрузчики (Loaders)

Обратите внимание, что в примере выше для локального изображения указан частичный 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 (CLS). Способ избежать сдвига макета из-за изображений — всегда указывать их размеры. Это позволяет браузеру заранее зарезервировать достаточно места для изображения.

Поскольку 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 для инлайн-стилей.
    • Нельзя использовать 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. Эти настройки позволяют разрешить удалённые изображения, определить пользовательские брейкпоинты изображений, изменить поведение кэширования и многое другое.

Подробнее о конфигурации изображений.