Перейти к содержанию

Начало работы с NgOptimizedImage

📅 7.11.2022

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

Директива обеспечивает приоритет загрузки изображения Largest Contentful Paint (LCP) путем:

  • автоматической установки атрибута fetchpriority в теге <img>.
  • ленивой загрузки других изображений по умолчанию
  • Утверждение, что в шапке документа есть соответствующий тег ссылки preconnect
  • Автоматическое создание атрибута srcset.
  • Генерирование preload hint, если приложение использует SSR.

В дополнение к оптимизации загрузки изображения LCP, NgOptimizedImage применяет ряд лучших практик для изображений, таких как:

Начало работы

Шаг 1: Импорт NgOptimizedImage

1
import { NgOptimizedImage } from '@angular/common';

Директива определена как отдельная директива, поэтому компоненты должны импортировать ее напрямую.

Шаг 2: (Необязательно) Настройка загрузчика

Загрузчик изображений не является обязательным для использования NgOptimizedImage, но его использование с CDN для изображений позволяет получить мощные возможности производительности, включая автоматический srcsets для ваших изображений.

Краткое руководство по настройке загрузчика можно найти в разделе Configuring an Image Loader в конце этой страницы.

Шаг 3: Включить директиву

Чтобы активировать директиву NgOptimizedImage, замените атрибут src вашего изображения на ngSrc.

1
<img ngSrc="cat.jpg" />

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

Шаг 4: Пометьте изображения как priority

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

1
<img ngSrc="cat.jpg" width="400" height="200" priority />

Пометка изображения как приоритетного применяет следующие оптимизации:

  • Устанавливает fetchpriority=high (подробнее о приоритетных подсказках здесь).
  • Устанавливает loading=eager (подробнее о нативной ленивой загрузке здесь).
  • Автоматически генерирует элемент preload link element, если rendering on the server.

Angular выводит предупреждение во время разработки, если LCP-элемент является изображением, у которого нет атрибута priority. LCP-элемент страницы может меняться в зависимости от ряда факторов — например, от размеров экрана пользователя, поэтому на странице может быть несколько изображений, которые должны иметь атрибут priority. Более подробную информацию см. в CSS для веб-страниц.

Шаг 5: Укажите высоту и ширину.

Чтобы предотвратить смещение макета, связанное с изображением, NgOptimizedImage требует, чтобы вы указали высоту и ширину изображения, как показано ниже:

1
<img ngSrc="cat.jpg" width="400" height="200" />

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

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

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

Использование режима fill

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

Когда вы добавляете атрибут fill к своему изображению, вам не нужно и не следует указывать width и height, как в этом примере:

1
<img ngSrc="cat.jpg" fill />

Вы можете использовать CSS-свойство object-fit, чтобы изменить, как изображение будет заполнять свой контейнер. Если стилизовать изображение с помощью object-fit: "contain", изображение сохранит соотношение сторон и будет "letterboxed", чтобы поместиться в элемент. Если задать object-fit: "cover", элемент сохранит свое соотношение сторон, полностью заполнит элемент, а часть содержимого может быть "обрезана".

Смотрите наглядные примеры вышеописанного в MDN object-fit documentation..

Вы также можете изменить стиль изображения с помощью свойства object-position, чтобы настроить его положение в содержащем его элементе.

Важное замечание: Чтобы изображение "fill" отображалось правильно, его родительский элемент должен быть стилизован с помощью position: "relative", position: "fixed", или position: "абсолютное`.

Настройка стилизации изображения

В зависимости от стиля изображения, добавление атрибутов width и height может привести к тому, что изображение будет отображаться по-разному. NgOptimizedImage предупреждает вас, если ваш стиль изображения отображает его с искаженным соотношением сторон.

Обычно это можно исправить, добавив height: auto или width: auto в стили изображения. Для получения дополнительной информации см. статью web.dev о теге <img>.

Если атрибуты height и width изображения не позволяют вам изменить размер изображения с помощью CSS, используйте режим "fill" и стилизуйте родительский элемент изображения.

Особенности производительности

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

Добавить подсказки для ресурсов

Вы можете добавить preconnect resource hint для происхождения вашего изображения, чтобы гарантировать, что изображение LCP загрузится как можно быстрее. Всегда помещайте подсказки ресурсов в <head> документа.

1
<link rel="preconnect" href="https://my.cdn.origin" />

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

Чтобы отключить эти предупреждения, введите маркер PRECONNECT_CHECK_BLOCKLIST:

1
2
3
providers: [
  {provide: PRECONNECT_CHECK_BLOCKLIST, useValue: 'https://your-domain.com'}
],

Запрашивать изображения нужного размера с помощью автоматического srcset

Определение атрибута srcset гарантирует, что браузер запросит изображение нужного размера для области просмотра пользователя, чтобы не тратить время на загрузку слишком большого изображения. NgOptimizedImage генерирует подходящий srcset для изображения, основываясь на наличии и значении атрибута sizes в теге изображения.

Изображения фиксированного размера

Если ваше изображение должно быть "фиксированного" размера (т.е. одинакового размера на всех устройствах, за исключением плотности пикселей), то нет необходимости устанавливать атрибут sizes. srcset может быть сгенерирован автоматически из атрибутов ширины и высоты изображения без необходимости дополнительного ввода.

Пример генерируемого srcset: <img ... srcset="image-400w.jpg 1x, image-800w.jpg 2x">.

Отзывчивые изображения

Если ваше изображение должно быть отзывчивым (т.е. увеличиваться и уменьшаться в зависимости от размера области просмотра), то вам необходимо определить атрибут sizes для генерации srcset.

Если вы раньше не использовали sizes, то для начала лучше всего установить его на основе ширины области просмотра. Например, если ваш CSS заставляет изображение заполнять 100% ширины области просмотра, установите sizes в 100vw, и браузер выберет изображение в srcset, которое ближе всего к ширине области просмотра (после учета плотности пикселей). Если ваше изображение будет занимать только половину экрана (например, в боковой панели), установите sizes в 50vw, чтобы браузер выбрал изображение меньшего размера. И т.д.

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

По умолчанию точками разрыва отзывчивости являются:

[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]

Если вы хотите настроить эти точки останова, вы можете сделать это с помощью провайдера IMAGE_CONFIG:

1
2
3
4
5
6
7
8
providers: [
  {
    provide: IMAGE_CONFIG,
    useValue: {
      breakpoints: [16, 48, 96, 128, 384, 640, 750, 828, 1080, 1200, 1920]
    }
  },
],

Если вы хотите вручную определить атрибут srcset, вы можете задать свой собственный с помощью атрибута ngSrcset:

1
<img ngSrc="hero.jpg" ngSrcset="100w, 200w, 300w" />

Если присутствует атрибут ngSrcset, NgOptimizedImage генерирует и устанавливает srcset на основе включенных размеров. Не включайте имена файлов изображений в ngSrcset — директива выводит эту информацию из ngSrc. Директива поддерживает как дескрипторы ширины (например, 100w), так и дескрипторы плотности (например, 1x).

1
2
3
4
5
<img
    ngSrc="hero.jpg"
    ngSrcset="100w, 200w, 300w"
    sizes="50vw"
/>

Отключение автоматической генерации srcset

Чтобы отключить генерацию srcset для отдельного изображения, вы можете добавить атрибут disableOptimizedSrcset к изображению:

1
<img ngSrc="about.jpg" disableOptimizedSrcset />

Отключение ленивой загрузки изображений

По умолчанию NgOptimizedImage устанавливает loading=lazy для всех изображений, которые не помечены как приоритетные. Вы можете отключить это поведение для неприоритетных изображений, установив атрибут loading. Этот атрибут принимает значения: eager, auto и lazy. Подробнее см. документацию по стандартному атрибуту loading для изображений.

1
2
3
4
5
6
<img
    ngSrc="cat.jpg"
    width="400"
    height="200"
    loading="eager"
/>

Расширенные значения 'sizes'

Вам может понадобиться отображать изображения разной ширины на экранах разного размера. Частым примером такой схемы является макет на основе сетки или колонок, который отображает одну колонку на мобильных устройствах и две колонки на больших устройствах. Вы можете описать это поведение в атрибуте sizes, используя синтаксис "медиазапроса", например, следующий:

1
2
3
4
5
6
<img
    ngSrc="cat.jpg"
    width="400"
    height="200"
    sizes="(max-width: 768px) 100vw, 50vw"
/>

Атрибут sizes в приведенном выше примере говорит: "Я ожидаю, что это изображение будет занимать 100 процентов ширины экрана на устройствах шириной менее 768px. В противном случае я ожидаю, что оно будет занимать 50 процентов ширины экрана".

Дополнительную информацию об атрибуте sizes смотрите в web.dev или mdn.

Настройка загрузчика изображений для NgOptimizedImage.

Загрузчик" — это функция, которая генерирует URL преобразования изображения для заданного файла изображения. Когда это необходимо, NgOptimizedImage устанавливает размер, формат и качество преобразования изображения.

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

Тип загрузчика Поведение
Общий загрузчик URL, возвращаемый общим загрузчиком, всегда будет совпадать со значением src. Другими словами, этот загрузчик не применяет никаких преобразований. Сайты, использующие Angular для работы с изображениями, являются основным вариантом использования этого загрузчика.
Загрузчики для сторонних сервисов изображений URL, возвращаемый загрузчиками для сторонних сервисов изображений, будет следовать соглашениям API, используемым этим конкретным сервисом изображений.
Пользовательские загрузчики Поведение пользовательского загрузчика определяется его разработчиком. Вы должны использовать пользовательский загрузчик, если ваш сервис изображений не поддерживается загрузчиками, которые поставляются с NgOptimizedImage.

Основываясь на сервисах изображений, обычно используемых в приложениях Angular, NgOptimizedImage предоставляет загрузчики, предварительно настроенные для работы со следующими сервисами изображений:

Сервис изображений Angular API Документация
Cloudflare Image Resizing provideCloudflareLoader Документация
Cloudinary provideCloudinaryLoader Документация
ImageKit provideImageKitLoader Документация
Imgix provideImgixLoader Документация

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

Встроенные загрузчики

Чтобы использовать существующий загрузчик для стороннего сервиса изображений, добавьте фабрику провайдеров для выбранного вами сервиса в массив providers. В примере ниже используется загрузчик Imgix:

1
2
3
providers: [
  provideImgixLoader('https://my.base.url/'),
],

Базовый URL для ваших активов изображений должен быть передан фабрике провайдера в качестве аргумента. Для большинства сайтов этот базовый URL должен соответствовать одному из следующих шаблонов:

  • https://yoursite.yourcdn.com
  • https://subdomain.yoursite.com
  • https://subdomain.yourcdn.com/yoursite

Подробнее о структуре базового URL вы можете узнать в документации соответствующего CDN-провайдера.

Пользовательские загрузчики

Чтобы использовать настраиваемый загрузчик, предоставьте свою функцию загрузчика в качестве значения для DI-токена IMAGE_LOADER. В приведенном ниже примере пользовательская функция загрузчика возвращает URL, начинающийся с https://example.com, который включает src и width в качестве параметров URL.

1
2
3
4
5
6
7
8
providers: [
  {
    provide: IMAGE_LOADER,
    useValue: (config: ImageLoaderConfig) => {
      return `https://example.com/images?src=${config.src}&width=${config.width}`;
    },
  },
],

Функция загрузчика для директивы NgOptimizedImage принимает в качестве аргумента объект с типом ImageLoaderConfig (из @angular/common) и возвращает абсолютный URL актива изображения. Объект ImageLoaderConfig содержит свойство src, а также необязательные свойства width и loaderParams.

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

Свойство loaderParams

Существует дополнительный атрибут, поддерживаемый директивой NgOptimizedImage, называемый loaderParams, который специально разработан для поддержки использования пользовательских загрузчиков. Атрибут loaderParams принимает в качестве значения объект с любыми свойствами и сам по себе ничего не делает. Данные в loaderParams добавляются в объект ImageLoaderConfig, передаваемый вашему пользовательскому загрузчику, и могут быть использованы для управления поведением загрузчика.

Чаще всего loaderParams используется для управления расширенными возможностями CDN для изображений.

Пример пользовательского загрузчика

Ниже показан пример функции пользовательского загрузчика. Эта функция конкатенирует src и width и использует loaderParams для управления функцией CDN для закругленных углов:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const myCustomLoader = (config: ImageLoaderConfig) => {
    let url = `https://example.com/images/${config.src}?`;
    let queryParams = [];
    if (config.width) {
        queryParams.push(`w=${config.width}`);
    }
    if (config.loaderParams?.roundedCorners) {
        queryParams.push('mask=corners&corner-radius=5');
    }
    return url + queryParams.join('&');
};

Обратите внимание, что в приведенном выше примере мы придумали имя свойства 'roundedCorners' для управления функцией нашего пользовательского загрузчика. Затем мы можем использовать это свойство при создании изображения, как показано ниже:

1
2
3
4
5
6
<img
    ngSrc="profile.jpg"
    width="300"
    height="300"
    [loaderParams]="{roundedCorners: true}"
/>

Комментарии