Если вам кажется, что загрузить картинку на сайт – это пара пустяков, наша статья для вас. Мы расскажем, почему длина пути от добавления изображения в админку до вывода его на экран зависит от того, какое качество вы хотите видеть в результате.
Возможно, вам случалось сталкиваться с такими косяками:
Возможно, вам случалось сталкиваться с такими косяками:
долгая загрузка картинки
на айфоне плохое качество изображения
на фотографии обрезало кому-то голову
баннер на десктопе красивый, а не телефоне не видно контактных данных
Знайте, там пошли по наименьшему пути сопротивления и не уделили должного внимания способам загрузки изображения на сайт или в приложении. Поэтому расскажем, как наша команда работает с картинкам в проектах.
Дисклеймер: статья написана в феврале 2022 года. Использованы актуальные инструменты для этого времени.
Где хранить изображения для сайта?
Для хранения картинок мы используем S3. Это такой протокол для работы с файлами, который раньше ассоциировался только с сервисами Amazon, но сейчас его можно развернуть самому, или использовать много готовых решений. Например, в том же Яндексе. Фишка S3 хранилищ, что они “резиновые” и условно бесконечные. Если в приложении постоянно добавляются новые картинки, а вы не представляете, сколько их будет, и не хотите следить за свободным местом на диске, постоянно масштабировать его, то хранилище S3 – пока лучшее решение. Вы платите только за то, сколько места используете.
Кстати, особенно актуальна эта проблема для сервисов и e-comm. В нашей практике случалось, что ночью обновлялся каталог, и появлялись десятки гигабайт фотографий, а место на сервере заканчивалось. Используя S3, можно застраховать себя от этого.
Как ресайзить картинки для веба или приложений?
Для работы с картинками мы используем https://imgproxy.net. Он у нас развернут как отдельный микросервис и присутствует в каждом проекте. Ранее мы делали ресайз картинок на PHP, так как это наш основной стек, потом перешли на node.js, но по итогу решили, что https://imgproxy.net – более гибкий вариант, написанный на языке Go, с кучей настроек и высокой скоростью работы. Что еще круто, есть не только ресайз, но и водяные знаки, центрирование и много чего другого – смотрите на сайте.
Как подготовить картинку для веба?
В вебе мы используем 2 формата картинок: webp и jpg. Webp на данный момент – наиболее современный из стабильных форматов, который поддерживают почти все браузеры. Он предполагает хорошее качество и небольшой вес. Для тех, кто не поддерживает webp, грузим jpg.
Еще есть разные разрешения. Мы ориентируемся на 3 контрольных размера: мобайл, десктоп и планшет. Правильнее для каждого разрешения использовать свою картинку, чтобы телефон получал нужный для него размер и подгружал ровно то, что требуется ему, а десктоп – себе. Бывает же такое, что на одном устройстве картинка 300 на 400, а на другом – 100 на 100.
Помимо этого есть такой показатель как плотность точек на экране. Например, вы слышали про retina экраны в Apple. Так вот сейчас плотность пикселей на один физический пиксель бывает и 2, и 3. Это можно проверить, например, здесь. Выходит, что нам требуется дополнительно делать подходящие для каждого экрана картинки со своей плотностью.
В итоге мы получаем целое комбо изображений, которое формируется в зависимости от браузера, разрешения, плотности экрана. Например, есть карточка товара в каталоге. Для одной такой позиции мы генерируем 3 разрешения (десктоп, планшет, мобайл), 2 формата (jpg и webp) и подходящие по плотности экрана 1X, 2X, 3X картинки.
Фронтенд составляет требования для картинок таким образом.
А на бэкенде мы формируем целый массив картинок.
Как результат 1 загруженная картинка на примере каталога на выходе имеет 48 вариантов картинок различных размеров, разрешений и форматов.
Ситуация в целом очень схожа с вебом. Повторяться не будем. Но есть особенности с поддержкой форматов. Например, webp поддерживает ios>15 версии, android – с 11.
Так как приложения мы делаем только на react native, компонент со стороны react native выглядит следующим образом.
Какого качества должны быть картинки для веба и мобайла?
В imgproxy, который мы используем для ресайза картинок, можно определять процент качества от исходного. Здесь следует найти баланс, ведь уменьшая этот параметр, вы уменьшаете и объем, но, соответственно, снижаете степень детализации. А если поставить 100% качество, получается “тяжелое” изображение.
Опытным путем мы для себя выбрали качество для webp 85%, для jpg – 95%.
Как кэшировать изображения?
На выходе получается, что для одной картинки мы имеем десятки изображений разных форматов и разрешений. Где все их хранить? Один из способов – при загрузке или появлении картинки в системе создавать сразу все необходимые варианты и статично хранить в S3.
Но потом начали наблюдать ситуацию, при которой очень быстро увеличивается объем хранилища и усложняется его поддержка, если появляется дополнительный размер. Например, создается новая страница на сайте, где нужен другой размер картинки с товаром. В итоге приходится пройтись по всем старым файлам и создать плюс один размер, что долго.
Поэтому мы пришли к варианту, когда в момент запроса картинки создаются необходимые варианты и складываются в кэш. За счет скорости работы imgproxy это довольно быстрая операция. Такой кэш хранится 1 месяц. В итоге у нас в кэше только картинки, которые часто запрашиваются, поэтому они отдаются быстро. А к товарам, которые, например, никогда не открывались на сайте, даже не создаются такие варианты картинок.
Вот какой долгий путь проходит картинка, в простой на первый взгляд схеме, где вы загружаете изображение, а мы выводим его на сайте. Все это для оптимизации и хорошего качества.