12 июн. 2023
РедактироватьPhoto lib share - фото галерея своими руками
Идея написать свою фото галерею появилась у меня пару лет назад. И даже начал что-то писать, но довольно быстро забил. С тех времён у меня была почти готовая библиотека для создания красивого лэйаута. Photo flex layout - это имплементация Google Photo Flex Layout. Выпустил версию 1.0.0, подробнее про неё писал в Telegram канале.
В планах написать два модуля:
Photo lib
- приложение для хранение и организации фоточек. Ставится он должен в идеале на NAS. Пока он не написан, использую synology photos. Но единственный его плюс, это неплохая синхронизация через мобильное приложение, в остальном одни минусы. Нет возможности посмотреть все фото наа карте, raw и jpeg не объединяются в одно фото, нет архива, нельзя поставить условиеand
при фильтрации по тегам. И это первое что пришло в головуPhoto lib share
- галерея для шеринга фоточек и альбомов. Ставится он должен куда-нибудь на публичный сервер, чтоб можно было смотреть на фоточки даже еслиPhoto lib
не доступен. Начать я решил именно с этого модуля.
В данный момент готов MVP. Посмотреть на работу можно на dskr.photos. Исходники на GitHub.
Нулевая версия
Начал с того что взял старый код, выкинул всё что было не нужно, обновил зависимости и заставил это всё хоть как-то работать. Превью подготавливал с помощью sharp, mozjpeg, 80%, 1000 пикселей по длиной стороне. Превью генерировались во время индексации, что не очень удобно. Между беком и фронтом, просто http, на сервере koa. Метадата хранится в nedb. Эту версию так никуда и не выложил.
Первая версия
Добавил docker compose для нормального деплоя. Пришлось изучить как правильно писать докерфайлы. Долго матерился.
Базу поменял на postgres, взял orm prisma. До этого обычно использовал sequelize, это был первый опыт работы с призмой. В целом понравилось, из косяков, при кодогенерации нужно задавать валидную переменную окружения с строкой подключения к базе, что не очень хорошо ложится на логику использования докера. Описал одну единственную таблицу с нужными и не очень полями.
Sharp поменял на imgproxy. Но это оказалось плохое решение. В целом imgproxy клёвый, но он явно сделан не для этого. Из косяков, imgproxy не умеет в кеширование, всё что он делает, это выставляет правильные заголовки кеширования. Для решения этой проблемы пришлось настроит кеширующий nginx. Но проблему первого открытия это всё равно не решило, большие фоточки конвертировались медленно. Превью запрашивал под необходимый размер, но чтоб работало кеширование, округлял до 25 в большую сторону.
Lightbox быстро написал сам, получилось плохо не удобно и не красиво.
Сделал нормальный монорепозиторий. Для управления взял turborepo. Сразу вынес отдельно будущий общий код Photo lib
и Photo lib share
.
Задеплоил, собрал фидбек. Ожидаемо всё было плохо с lightbox. Так же загружались оригиналы в lightbox, что тоже не оч хорошая идея.
Вторая версия
Поменял схему базы. Теперь у меня есть Image
с основной информацией вроде времени создания и exif. File
с ссылкой на оригинальное фото. Thumbnail
с ссылкой на всевозможные превью.
Выкинул imgproxy, вернул sharp. Теперь генерю webp и avif. Качество пока выставил 80 для webp и 65 для avif. Хотел добавить ещё heif и jxl, но для них нужно руками собирать плюсовую либу. Генерирую два размера, полноразмерную превью для показал в lightbox и 720px по длинной стороне для галереи. Так как avif генерируются медленно, использую очередь и отдельный поток для генерации. Для очереди пока что взял bullmq. Если никакой превью ещё не сгенерировано, то загружаю оригинальную фотку.
Выкинул самописный lightbox и взял photoswipe. Выбрал его в первую очередь из-за красивой анимации открытия фотки. Photoswipe написан без фреимворков, но его можно подключить например к реакту. Из косяков, у меня не подтягиваются типы. Так же взял framer-motion для красивой анимации появления фоток в галерее. Не уверен что это хорошее решение, но пока решил оставить так.
Взял tRPC вместо koa. Хотел попробовать Garph, но он пока что очень сырой, писал про это в Telegram канале. tRPC достаточно стабильный и удобный. Но мне не нравится что фронтенд проект импортирует бэкенд проект. Как минимум это замедляет билд. В идеале хотелось бы иметь возможность вынести схему отдельно, но пока не понял как это сделать удобно.
Добавил telegram бота для администрирования и загрузки фоток. Для этого взял grammY. Пока что бот умеет только загружать фотки, и запускать принудительную переиндексацию. Из ограничений, нельзя загружать фото больше 20мб, это можно обойти если самому хостить bot api, но пока что мне не хочется с этим разбираться.
Добавил Reproxy для простенькой реверспрокси. Nginx я настраивать не умею, а caddy кажется overkill для таких задач. Хотел чтоб всё красиво работало через лейблы, но почему-то не смог завести на маке docker sock. Но, меня и статичный конфиг устраивает.
ToDo
Планирую заменить bullmq на rabbitmq. Bullmq всем хорош, но он работает только с нодой и в экспериментальном режиме питоном. А хочется иметь больший выбор платформ.
Хочется попробовать перенести генерацию превью на rust. Это должно быть быстрее. Надеюсь что там не будет проблем с поддержкой модных форматов. Но я совсем не знаю раст, и это не тот язык который можно освоить за выходные.
Надо бы добавить альбомы. Но пока что не придумал как они должны выглядеть. Так же под это дело прийдётся дорабатывать бота.
Ну и уже можно начинать думать о работе над Photo lib
. Там у меня куда больше планов.