Next.jsJuniorTechnical

Как компонент Image в Next.js оптимизирует изображения?

next/image автоматически конвертирует изображения в WebP/AVIF, генерирует srcSet для разных экранов, добавляет lazy loading и резервирует место для предотвращения CLS. Удалённые домены нужно явно разрешить в remotePatterns.

Компонент Image в Next.js

Компонент next/image — это расширенный <img>, который автоматически оптимизирует изображения на лету через встроенный Image Optimization API.

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

import Image from "next/image";
import profilePic from "./avatar.jpg"; // статический импорт

export function Avatar() {
  return (
    <Image
      src={profilePic}
      alt="User avatar"
      width={64}
      height={64}
      priority // LCP-изображениезагружать сразу
    />
  );
}

// Удалённое изображение — нужен домен в конфиге
export function RemoteImage() {
  return (
    <Image
      src="https://cdn.example.com/photo.jpg"
      alt="Photo"
      width={800}
      height={600}
      sizes="(max-width: 768px) 100vw, 50vw"
    />
  );
}

Что происходит под капотом

  • Конвертация в WebP/AVIF — браузер получает оптимальный формат через Accept заголовок. AVIF меньше WebP на 20-50%.
  • Ресайз под устройство — генерируются srcSet для экранов разных плотностей. Телефон с 375px экраном не скачивает 1920px изображение.
  • Lazy loading по умолчаниюloading="lazy" добавляется автоматически, если не указан priority.
  • Предотвращение layout shift — резервирует место под изображение через CSS до его загрузки, CLS = 0.
  • Кеширование — оптимизированные варианты кешируются на диске и отдаются с Cache-Control: public, max-age=31536000.

fill режим для изображений без известных размеров

export function HeroBanner() {
  return (
    <div style={{ position: "relative", width: "100%", height: "400px" }}>
      <Image
        src="/hero.jpg"
        alt="Hero"
        fill
        style={{ objectFit: "cover" }}
        sizes="100vw"
        priority
      />
    </div>
  );
}

Настройка допустимых доменов

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "cdn.example.com",
        pathname: "/images/**",
      },
    ],
    formats: ["image/avif", "image/webp"],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920],
  },
};
module.exports = nextConfig;

Подводные камни

  • Для удалённых изображений обязательно указывать домен в remotePatterns — без этого next build проходит, но runtime возвращает 400.
  • priority нужно указывать только для LCP-изображения (первый экран). Если добавить его всем изображениям, потеряется смысл lazy loading.
  • При использовании fill родительский элемент обязательно должен иметь position: relative (или absolute/fixed) — иначе изображение не отображается.
  • Атрибут sizes критичен для производительности: без него Next.js генерирует srcSet, но браузер скачивает полноразмерное изображение. Всегда указывайте корректные breakpoints.
  • Image Optimization работает на сервере — на статическом экспорте (output: "export") next/image не работает без кастомного loader.
  • SVG файлы не оптимизируются компонентом Image по умолчанию — используйте обычный <img> или SVGR для SVG.
  • Кеш оптимизированных изображений хранится в .next/cache/images — при деплое без сохранения кеша первые запросы будут медленными.

Common mistakes

  • Не указывать width/height (или fill) — CLS
  • Забыть remotePatterns для внешних URL
  • Ставить priority на все изображения
  • Использовать next/image для SVG-иконок

What the interviewer is testing

  • Знает форматы AVIF/WebP и srcset
  • Понимает значение priority и LCP
  • Умеет настроить remotePatterns
  • Учитывает биллинг и кеш в production

Sources

Related topics