Привет Хабр!
Сегодня я хотел бы поговорить с тобой о проблеме публикации картинок. Зачем вообще об этом говорить? Ежедневно миллионы людей публикуют миллионы, или даже, миллиарды изображений, что тут можно обсуждать? Наверняка, для веб-разработчика, тем более, опытного — это вообще никакая не проблема. Эх, как бы не так.
Начну я с описания того ракурса, с которого лично я смотрю на этот вопрос. Возможно, это добавит красок в техническое повествование.
Я — фуллстек-разработчик, который специализируется на проектах, со значительным уклоном в R&D. Мне часто бывает нужно публиковать побочные артефакты своей работы, такие как веб-страницы с документацией, техническими статьями, интерактивные демо, прототипы и эксперименты, какие-то промо-страницы и так далее. Естественно, все это должно быть проиллюстрировано скриншотами интерфейсов, диаграммами, различными примерами рендеров и прочими фотками котиков.
При этом, я предпочитаю подходы и практики, которые минимизируют переключения контекстов и разрастание количества сущностей, с которыми приходится взаимодействовать. Это позволяет мне быть более эффективным. Доки и статьи я пишу прямо в IDE, в формате markdown, храню их в git. Сборка и публикация в веб, происходит автоматически, через git-хуки и экшены. Это делает совместную работу с коллегами-технарями комфортной, а наши общие бизнес-процессы — более легковесными. В идеале, я хочу, чтобы картинки тоже были частью такого дзена. Но…
Первый вопрос «курицы и яйца»: чтобы картинку разместить на странице, сперва, нужно получить ее URL. Самый простой, на первый взгляд, способ — относительный путь. Вы просто сохраняете картинку где-то в структуре своего проекта и публикуете вместе с остальными файлами.
CDN
Мы не хотим хранить картинки в git. Я надеюсь, вы тоже. Особенно, если их много. Потому, что это увеличивает размер репозитория, замедляет клонирование и синхронизацию, увеличивает время сборки и так далее. Мы хотим, чтобы картинки были отдельно, где-то в облаке. Желательно, в специальном CDN, чтобы не жечь лишний трафик нашего основного сервера и ускорить загрузку страниц у уважаемых читателей и пользователей. Использование таких CDN уже давно стало устоявшейся хорошей практикой.
Перед нами встает новый вопрос: как подружить наш легковесный воркфлоу с необходимостью взаимодействия с отдельным внешним сервисом? Ведь нам, все еще, нужны и удобная совместная работа и автоматизации и чувство превосходства над теми, кто все делает вручную, через всякие неудобные чужие UI…
Что еще необходимо учитывать: CDN сервисы, как правило, создают плоскую структуру хранения, где, для доступа, есть уникальный идентификатор загруженного ассета и более ничего. Да, часто вы можете получить дополнительные мета-данные отдельным запросом, с использованием вашего ключа доступа к API, но это далеко не всегда удобно и применимо.
Адаптивность
Идем далее. В современном мире, мало просто вставить тег <img>
с атрибутом src="..."
. Нам нужно позаботиться о пользователях с разными эранами, имеющими разную плотность пикселей. Иначе, одни увидят «мыло», а другие — скачают больше бесполезных мегабайт (а мы их оплатим). Также, нам нужно позаботиться о оптимальном формате (webp, avif и тд.). И, ко всему прочему, нам нужны, разные размеры картинок для разных лейаутов (мобильный, десктопный и т.д.).
Хорошо, что за подготовку множества вариантов, отвечают CDN-сервисы и нам не нужно заботиться о их генерации. Но HTML-код вставки, который учитывает все необходимое, получается довольно громоздким, и писать его вручную каждый раз — очень не хочется. А хочется — иметь удобный инструмент, который сделает это сам, в согласии с нашими настройками.
Веб-медиа-ассет-менеджмент мечты
Итак, опишу свой идеал, в рамках описанных целей. Вот примерный список того, что я хочу:
-
Совместная работа с медиа-коллекцией проекта через Git (но без загрузки оригиналов изображений в репозиторий)
-
Автоматическая синхронизация локальной медиа-директории с CDN (Как в Dropbox, примерно: кинул файлы в папку, и они сами улетели в облако)
-
Обязательная поддержка локальной структуры каталогов (маппинг адресов вложенных папок на ID файла в CDN)
-
Генерация HTML-кода вставки с поддержкой адаптивности, ленивой загрузки и прочих современных фишек (srcset, sizes, loading=»lazy»)
-
Возможность сортировки и фильтрации изображений по метаданным
-
Возможность просмотра и редактирования облачных коллекций, без необходимости иметь локальные копии файлов всем участникам процесса
-
Возможность загрузить и сохранить локальные копии, при необходимости
-
Хранение данных о загрузках в формате, удобном для использования в CI/CD пайплайнах, и для любой другой автоматической обработки (JSON)
-
Локально доступный веб-интерфейс управления, без необходимости заводить дополнительный аккаунт и авторизоваться в отдельном сервисе
-
Привязка облачных коллекций к проектам, а также, возможность использования общих ресурсов разными проектами
-
Легкость решения. Отсутствие бесконечной простыни зависимостей. Простота для аудита и модификаций.
-
Независимость от провайдера CDN-услуг
Еще немного личной истории
Я давно имею дело с технической стороной всей этой картиночной кухни. Когда-то, я руководил стартапом: мы делали сервис для публикации фото-360. Фото-360 — это такой способ интерактивного отображения, который позволяет осмотреть объект со всех сторон, используя для этого последовательность фотографий, сделанных с разных ракурсов. Вы, наверняка, видели такое на страницах некоторых интернет-магазинов, где товары можно крутить мышкой. Тот стартап не выжил, но оставил после себя богатый опыт, применимый во многих аспектах. Особенностью сервиса была загрузка ОЧЕНЬ большого количества картинок пользователями: для всего одной интерактивной публикации могла понадобиться более чем сотня исходных фотографий.
Какое-то время спустя, я отвечал за разработку набора виджетов для загрузки и отображения файлов в одной компании, предоставляющей услуги CDN.
Помимо этого, я постоянно экспериментирую и что-то публикую, как для своих текущих проектов, так и для души.
И, не смотря на весь свой опыт, я так и не нашел готового решения, которое бы полностью удовлетворяло как меня самого, так и мою команду. В один прекрасный момент, нас это окончательно задолбало, и мы решили сделать свое.
CIT — Cloud Images Toolkit

Не хочу, чтобы меня обвинили в саморекламе, поэтому, сразу уточню, что далее речь пойдет о бесплатном Open Source инструменте, который никак не монетизируется. Моя главная цель — поделиться с аудиторией историей конкретного решения, а также, подходами, которые мы, с командой, выработали в процессе. Целью номер два, является попытка получить фидбек и мотивацию для дальнейшего развития полезного инструмента.
Итак, CIT (Cloud Images Toolkit) — это инструмент рабочего окружения веб-разработчика, который позволяет автоматизировать процесс работы с медиа-контентом в веб-проектах. Он включает в себя утилиту для синхронизации локальной директории с CDN, а также, веб-интерфейс для просмотра и управления коллекциями изображений.
Ссылка на GitHub проекта: https://github.com/rnd-pro/cloud-images-toolkit
На текущем этапе, CIT адаптирован для работы с CDN-сервисом Cloudflare Images, но, в принципе, независим от него. При наличии интереса, мы можем добавить встроенную поддержку для любых других провайдеров. Но адаптер под используемый вами сервис — вопрос совсем не сложный и вы можете добавить его самостоятельно, при необходимости. Позже я планирую написать простую инструкцию, как это сделать на Node.js.
Установка:
npm install --save-dev cloud-images-toolkit
Конфигурация (файл cit-config.json) в корне проекта:
{ "syncDataPath": "./cit-sync-data.json", "imsDataPath": "./ims-data.json", "imgSrcFolder": "./cit-store/", "apiKeyPath": "./CIT_API_KEY", "projectId": "<YOUR_PROJECT_ID>", "imgUrlTemplate": "https://<YOUR_DOMAIN>/images/{UID}/{VARIANT}", "previewUrlTemplate": "https://<YOUR_DOMAIN>/images/{UID}/{VARIANT}", "uploadUrlTemplate": "https://api.cloudflare.com/client/v4/accounts/{PROJECT}/images/v1", "fetchUrlTemplate": "https://api.cloudflare.com/client/v4/accounts/{PROJECT}/images/v1/{UID}/blob", "removeUrlTemplate": "https://api.cloudflare.com/client/v4/accounts/{PROJECT}/images/v1/{UID}", "variants": ["120", "320", "640", "860", "1024", "1200", "2048", "max"], "imgTypes": ["png", "jpg", "jpeg", "webp", "gif", "svg"], "wsPort": 8080, "httpPort": 8081 }
На что тут следует обратить внимание:
imgSrcFolder
— путь к локальной директории с изображениями, которую следует добавить в .gitignore
, как и файл указанный в apiKeyPath
;
Варианты размеров картинок и их форматы — задаются в конфиге. При синхронизации, CIT автоматически генерирует все варианты для каждого изображения, используя шаблоны URL. При этом, важно, чтобы ваш CDN поддерживал автоматическое изменение размеров и конвертацию форматов. В случае с Cloudflare Images, это делается в настройках сервиса. Имена вариантов должны содержать размер изображения в пикселях, или ключевое слово max
, для оригинала. Например, если в вашем шаблоне используется изображение шириной 320px
, то вам нужно добавить вариант 320
и вариант 640
для экранов с двойной плотностью пикселей.
Маппинг локальной структуры каталогов реализован через строку содержащую локальный путь к картинке. Для фильтрации изображений в UI используется ее подстрока, поэтому, желательно, следить за тем, чтобы названия папок были, по возможности, уникальными а общая структура коллекции — осмысленной.
IMS — Interactive Media Spots
CIT поддерживает генерацию интерактивных виджетов, использующих ваши облачные изображения. Для этого используется OpenSource (MIT) библиотека виджетов — IMS (https://github.com/rnd-pro/interactive-media-spots).

В заключение
Если у вас будут вопросы по внедрению и использованию — пишите, с удовольствием отвечу на них в комментариях. Проект совсем молодой и сейчас активно используется как наш внутренний рабочий инструмент. Поэтому, конечно же, буду рад любому фидбеку, звездочкам на GitHub, предложениям по улучшению или сотрудничеству.
Ну, и собственных планов по развитию инструмента, конечно, у нас полно. Например, встроенная генерации изображений с помощью ИИ, управление промптами, авто-генерация описаний (alt) для лучшего SEO, поддержка видео-коллекций (потоковое видео), раздел дэшборда для работы с коллекциями объектов IMS, разделение файла описания медиа-коллекции на части и менеджмент разных коллекций… И так далее.
Спасибо за внимание.
ссылка на оригинал статьи https://habr.com/ru/articles/891696/
Добавить комментарий