tgoop.com/super_oleg_dev/63
Last Update:
Учитывая уже развернутый сервис imgproxy, я решил делать Image компонент поверх этого сервиса - это закрыло вопросы лишней нагрузки на SSR приложения, оптимизации под разные форматы, отдачи нужного формата в рантайме без тега picture (что позволяет сделать очень простую разметку).
Еще не решенная проблема этого выбора - невозможность использовать сервис при разработке, для изображений на localhost..avif формат у нас был отключен из-за высокой нагрузки при генерации изображений в этом формате, было интересно разобраться в проблеме, даже помогли немножко улучшить сервис - https://github.com/imgproxy/imgproxy/issues/938.
Оказалось, что для достижения сравнимого качества изображения, для AVIF надо указывать значительно более низкий уровень качества при оптимизации, хорошее сравнение форматов можно найти тут - https://www.industrialempathy.com/posts/avif-webp-quality-settings/
В итоге, после точечной настройки, мы подключили AVIF, и в среднем, с примерно одинаковым качеством, это снизило размер итоговых изображений на 30-50% по сравнению с webP.
Следующий кейс - автоматическое сохранение пропорций, вычисление aspect-ratio.
На примере некста, логику получения размера картинки можно встроить в сборку - https://github.com/vercel/next.js/blob/canary/packages/next/build/webpack/loaders/next-image-loader.js.
В tramvai я добавил простой лоадер, который переиспользует логику file-loader (компромисс, т.к. по хорошему надо использовать Asset Modules), но при именованном импорте отдает объект с данными об изображении, которые необходимы для сохранения пропорций:jsx
import { image } from './image.png';
const { src, width, height } = image;
<img src={src} width={width} height={height} />
По аналогии с next/image, добавил в компонент несколько вариантов верстки (и без необходимости поддерживать старые браузеры и наличии aspect-ratio, верстка невероятно простая):
- адаптивная, но не больше размера изображения (intrinsic)
- резиновая под размер контейнера (responsive)
- фиксированный размер (fixed)
- заполняющая доступное пространство (fill)
Если для intrinsic и fixed изображений достаточно учесть только плотность пикселей на экране, и передать в srcset 1x и 2x изображения, то для оптимальной responsive и fill верстки srcset должен содержать изображения под совершенно разные размеры экранов.
По этой причине, отдельной задачей было исследовать аналитику посещения наший приложений на tinkoff.ru для создания минимального но в то же время полного списка экранов, которые мы будем учитывать в srcset при генерации изображений.
Пример размеров из этого списка:
- 720px - популярная ширина мобилок 360px плюс 2x плотность пикселей
- 1366px - популярная ширина на десктопе
- 3840px - еще одна популярная ширина на десктопе, 1920px плюс 2x плотность пикселей
Таким образом, пользователи большинства устройств получат изображение минимально необходимого размера и оптимального качества.
Еще из интересного, простые и удобные абстракции:
- Свойство quality - позволяет при необходимости сконфигурировать оптимизацию через imgproxy более высокого качества, или наоборот более низкого
- Свойство priority - по умолчанию делаем все изображения c loading="lazy", но можем повысить приоритет и убрать этот атрибут, а с самым высоким приоритетом автоматически добавляем preload link на страницу для этой картинки (тривиальная задача для SSR фреймворка), что идеально подходит для Largest Contentful Paint изображения
Это был очень интересный опыт, и интересно как дальше будет развиваться новый Image компонент.
Например, в будущем я планирую отвязать его от imgproxy, и перенести в список публичных пакетов, которые публикуются в open-source.
Также, надо будет выбрать хороший способ создания blur плейсхолдера для изображений.
BY SuperOleg dev notes
Share with your friend now:
tgoop.com/super_oleg_dev/63
