Чуть больше года назад команда Chrome Aurora запустила директиву Angular NgOptimizedImage . Директива направлена в первую очередь на повышение производительности, измеряемой показателями Core Web Vitals . Он объединяет общие оптимизации изображений и лучшие практики в API, ориентированный на пользователя, который не намного сложнее стандартного элемента <img>
.
В 2023 году мы дополнили директиву новыми функциями. В этом посте описываются наиболее существенные из этих новых функций с акцентом на то, почему мы решили расставить приоритеты для каждой функции и как это может помочь улучшить производительность приложений Angular.
Новые возможности
NgOptimizedImage со временем существенно улучшился, включая следующие новые функции.
Режим заполнения
Изменение размера изображений с помощью атрибутов width
и height
— чрезвычайно важная оптимизация для уменьшения смещения макета , поскольку браузерам необходимо знать соотношение сторон изображения, чтобы освободить для него место. Однако определение размера изображений является дополнительной работой для разработчиков приложений и не имеет смысла в некоторых случаях использования изображений.
Разрешить это противоречие помогает первая важная функция, добавленная в предварительный просмотр компонента изображения после разработки: режим заливки . Это способ для разработчиков включать изображения без явного изменения их размера и без изменения макета.
В режиме заливки требование к размеру изображения отключается, и изображение автоматически стилизуется так, чтобы заполнить содержащий его элемент. Это отделяет соотношение сторон изображения от места, которое оно занимает на странице, и дает вам больший контроль над тем, как изображения вписываются в макет вашей страницы.
Режим заполнения использует NgOptimizedImage как более эффективную альтернативу свойству CSS background-image
. Поместите изображение внутри <div>
или другого элемента, который имел бы стиль background-image
, затем включите режим заливки, как показано в предыдущем примере кода. Используйте свойства CSS object-fit
и object-position
в <div>
чтобы контролировать расположение изображения на заднем плане.
// Height and width are required
<img ngSrc="example.com" height="300" width="400">
// Unless you use fill mode!
<div style="width: 100vw; height: 50em; position: relative">
<img ngSrc="example.com" fill>
</div>
Генерация исходного набора
Одним из наиболее эффективных методов оптимизации изображений является использование атрибута srcset
, который гарантирует загрузку изображений правильного размера для любого устройства, обращающегося к вашему приложению. Использование srcset
в вашем приложении может предотвратить потерю пропускной способности и существенно улучшить LCP Core Web Vital .
Недостатком атрибута srcset
является то, что его реализация может быть сложной. Запись значений srcset
вручную означает добавление нескольких строк разметки к каждому элементу изображения в вашем приложении, а также несколько пользовательских URL-адресов для каждого srcset
. Вам также необходимо определиться с набором точек останова, что сложно, поскольку они могут представлять как плотность экрана, так и размеры области просмотра обычных устройств.
Вот почему добавление автоматической генерации srcset в директиву NgOptimizedImage стало важной вехой после запуска. Благодаря этому дополнению любое приложение, использующее CDN, поддерживающее изменение размера изображения, может автоматически добавлять полные настраиваемые наборы источников к каждому изображению, созданному с помощью директивы NgOptimizedImage.
Мы включили упрощенный API для установки свойства sizes
, которое используется для обеспечения того, чтобы каждое изображение получало правильный тип srcset
. Если вы не включите атрибут sizes
, мы будем знать, что изображение должно иметь фиксированный размер и должно получить зависящий от плотности набор исходных данных, как показано ниже:
<img src="www.example.com/image.png" srcset="www.example.com/image.png?w=400 1x, www.example.com/image.png?w=800 2x" >
Этот тип srcset гарантирует, что изображения будут отображаться в размере, учитывающем плотность пикселей устройства пользователя.
С другой стороны, если вы добавите свойство sizes
, NgOptimizedImage
сгенерирует адаптивный набор источников, включающий точки останова для многих распространенных размеров устройств и изображений, используя этот список точек останова по умолчанию:
[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]
Генерация предварительного соединения
Чтобы улучшить LCP, важно сократить время, которое пользователи тратят на загрузку образа LCP. В предыдущем разделе вы видели, как srcset
может помочь при передаче файлов изображений меньшего размера, но не менее важной оптимизацией является начало передачи как можно скорее. Один из способов сделать это — использовать теги link rel="preconnect"
для запуска подключения к вашему домену изображений.
С самого начала NgOptimizedImage предупреждал, если вам не удалось предварительно подключиться к домену вашего образа LCP, но предупреждение не является идеальным решением — мы бы предпочли просто решить проблему за вас. И это именно то, что теперь делает NgOptimizedImage с автоматической генерацией предварительного соединения .
Для поддержки этой функции мы используем статический анализ кода, чтобы попытаться обнаружить домены изображений в загрузчиках NgOptimizedImage и автоматически сгенерировать теги ссылок предварительного подключения для этих доменов. Все еще могут быть случаи, когда требуются ссылки на предварительное подключение вручную, но для большинства пользователей автоматическое предварительное подключение означает, что для хорошей производительности изображения требуется на один шаг меньше.
Расширенная поддержка пользовательских загрузчиков.
Ключевым элементом NgOptimizedImage является архитектура загрузчика, которая позволяет директиве автоматически генерировать URL-адреса, адаптированные к CDN изображений приложения. Для широко используемых CDN включен набор встроенных загрузчиков. Мы также предусматриваем использование пользовательских загрузчиков , которые позволяют интегрировать NgOptimizedImage практически с любым решением для хостинга изображений.
При запуске эти пользовательские загрузчики были ограничены в объеме и могли считывать только атрибут width
из элемента изображения. В ответ на отзывы пользователей мы добавили поддержку настраиваемой структуры данных loaderParams
, которая позволяет передавать произвольные данные из элемента изображения в пользовательский загрузчик. С расширением пользовательские загрузчики могут быть настолько простыми или сложными, насколько того требует инфраструктура изображений приложения.
В следующем примере показано, как простой пользовательский загрузчик может использовать API loaderParams
для выбора между двумя альтернативными доменами изображений:
const myCustomLoader = (config: ImageLoaderConfig) => {
if (config.loaderParams?.alternateDomain) {
return `https://alternate.domain.com/images/${config.src}`
}
return `https://primary.domain.com/images/${config.src}`;
};
Пример более сложного пользовательского загрузчика доступен в документации Angular .
Расширенное руководство по производительности изображений
До сих пор каждое предупреждение о производительности изображения, которое мы добавляли в Angular, было частью директивы NgOptimizedImage. Если вы не используете директиву в приложении, вы не получите никаких указаний по проблемам производительности изображений.
В Angular 17 мы расширяем объем рекомендаций по производительности изображений, включив в него все приложения Angular. Теперь, если мы обнаружим шаблоны изображений, которые, как мы знаем, снижают производительность, например, отложенную загрузку образа LCP или загрузку файла, который слишком велик для страницы, мы сообщим вам об этом, даже если вы этого не сделаете. используя NgOptimizedImage.
Производительность изображений важна для всех приложений, и мы рады продолжать создавать защитные ограждения, которые помогут предотвратить распространенные ошибки в приложениях Angular.
С нетерпением жду
Мы уже усердно работаем над разработкой следующего набора функций для NgOptimizedImage. Хотя производительность изображений остается нашей главной заботой, мы также хотели бы добавить функции, которые улучшат работу разработчиков, чтобы NgOptimizedImage оставался привлекательным вариантом для включения изображений в приложения Angular.
Одна из функций, которая является для нас приоритетной, — это заполнители изображений. Они обычно используются для улучшения внешнего вида загрузки изображений в веб-приложениях, но при неправильной реализации могут снизить производительность. Мы надеемся создать в NgOptimizedImage систему заполнителей изображений, ориентированную на производительность. Следите за обновлениями в нашем блоге , чтобы быть в курсе дальнейших анонсов!