От автора: каждый разработчик знает, что в вопросе веб-производительности и пользовательского опыта важно каждое изображение. Изображения – это низко висящие плоды оптимизации производительности. Сжатие без визуальной потери качества может принести пользу организациям путем снижения веса страниц без ущерба для работы пользователя, что повышает производительность и привлекает все больше аудитории. Существует множество техник, для определения того, какое изображение необходимо загрузить, но эти «правильные изображения» еще необходимо создать. Целью веб-разработчиков и сервисов по повышению производительности должно быть обеспечение всех пользователей на всех типах устройств и во всех браузерах оптимальными изображениями. (Другой целью должна быть доступность, но это тема для отдельной статьи!).
Определение нужных изображений
Существует несколько front-end методов для обслуживания правильных изображений, среди которых можно выделить медиа запросы для фоновых изображений и теги
С помощью @media запросов можно задать, какое фоновое изображение использовать под определенное разрешение экрана и плотность экрана. Например, на старый лэптоп можно посылать изображение lowers.jpg, а на iPad Pro – hires.jpeg:
1 2 3 4 5 6 7 8 9 |
header { background-image: url(img/hires_header.jpg); } @media only screen and (min-device-pixel-ratio: 2) and (min-width: 1024px) { header { background-image: url(img/hires_header.jpg); } } |
А что с изображениями переднего плана?
Техника клоунской машины 2013 года работала на том, что SVG в медиа запросах использовал в качестве размеров окна ширину и высоту контейнера, а не браузера. К счастью, текущая поддержка в браузерах тега picture и атрибута srcset позволяет забыть про этот трюк и picturefill полифил.
Основная проблема с изображениями переднего плана заключается в том, что у браузера есть доступ к размерам окна и плотности экрана, но до загрузки самой страницы браузер не знает размеры изображения относительно окна или размеров исходных файлов. Однако их знает разработчик, он может включить их.
Работа с picture, source и атрибутом srcset похожа на медиа запросы. Вы указываете, какое изображение переднего плана необходимо использовать под определенный размер окна и плотность экрана:
1 2 3 4 5 6 |
<picture> <source srcset="small_lowres.jpg, small_highres.jpg 2x" media="(max-width: 768px)"> <source srcset="default.jpg, default_highres.jpg 2x"> <source srcset="large_lowres.jpg, large_highres.jpg 2x" media="(min-width: 1024px)"> <img src="default.jpg" alt="image descriptor"> </picture> |
Обратите внимание: всегда вставляйте стандартный тег img в picture, в том числе и атрибут alt с описанием изображения.
Можно сделать так, чтобы простой тег подбирал наилучшее изображение без родительского тега picture и смежного тега source. Для этого необходимо воспользоваться атрибутами srcset и sizes.
1 2 3 4 5 6 7 8 |
<img src="default.jpg" srcset="large.jpg 1024w, medium.jpg 768w, default.jpg 420w" sizes="(min-width: 1024px) 1024px, (min-width: 768px) 90vw, 100vw" alt="image descriptor" /> |
При помощи атрибута type можно загружать изображения разных форматов:
1 2 3 4 5 6 |
<picture> <source srcset="photo.jxr" type="image/vnd.ms-photo"> <source srcset="photo.jp2" type="image/jp2"> <source srcset="photo.webp" type="image/webp"> <img srcset="photo.jpg" alt="My beautiful face"> </picture> |
Если код сверху для вас что-то новенькое, то JPEG-XR и старыйMIME-тип image/vnd.ms-photo используются для Windows Media Photo, проприетарного формата изображений Microsoft. Поддерживается в IE8+ и Microsoft Edge. JPEG 2000 – это jp2, будет отображаться в браузерах Safari при использовании разметки выше. WebP – формат изображений со сжатием без потери качества, работает в Opera и Chrome. Firefox выберет формат по умолчанию, PNG-A, SVG, GIF или JPEG.
В Firefox и IE8 необходимо прописывать JPEG или PNG фолбек. Firefox и Safari экспериментируют с поддержкой изображений формата WebP, однако по данным сайта CanIUse.com нет никаких намеков на ближайшую поддержку.
Если хотите разобраться в этих новых, но хорошо поддерживаемых функциях, а также научиться применять их, то по медиа запросам, picture и srcset есть несколько замечательных уроков.
Почти безграничная настройка
Одна из основных проблем кода в разделе выше заключается в том, что мы включили лишь малую часть возможных изображений, подходящих под медиа тип, размер и плотность пикселей. Прописать все брейкпоинты, разрешения и медиа типы для всех изображений можно, но сложно. Мне бы не хотелось писать все вручную. К счастью, задачу по созданию всех необходимых изображений под все возможные случаи можно автоматизировать.
Оптимальный вариант – написать на стороне сервера запрос на самое оптимальное изображение на основе трех из четырех критериев: размер окна, плотность пикселей на устройстве, поддерживаемый медиа тип в браузере и размер изображения относительно окна. Почему на основе трех из четырех? Потому что можно использовать то, что браузер и так понимает исходники, вам не нужно включать все возможные комбинации, просто парочку.
Если DOM записывается в браузер исключительно через клиентский JS, как бывает в большинстве React приложений, браузеру можно послать запрос на одно правильное изображение, однако пока код парсится, пользователь может наблюдать частично загруженный неинтерактивный экран (скриншот). В более общем сценарии, когда на сайте есть серверная часть, переписывать запрос на изображение в JS – неоптимальный вариант: браузер сначала загрузит оригинал при парсинге DOM, затем загрузит второе, уже оптимизированное изображение после обновления DOM.
Если вы используете технику прогрессивного улучшения, а вы должны, нужно отчетливо понимать, что как только распарсится HTML код изображения, будет загружен оригинал.
К сожалению, спецификация Client Hints, добавляющая информацию о соотношении пикселей на устройстве и ширине окна в поля заголовков HTTP запросов, реализована только в Blink браузерах (Chrome и Opera). Если знать браузер пользователя, разрешение и размер окна, обновление всех запросов на изображения можно автоматизировать, тем самым используя технику прогрессивного улучшения для серверных запросов. При помощи Client Hints можно подтвердить поддержку формата webP (Chrome и Opera поддерживают и клиентские подсказки и webP), разрешения и размера окна. На сайте Instart Logic есть скрипт Nanovisor, делающий то же самое для Client Hints. С его помощью можно посылать оптимизированные изображения в оптимизированных форматах, даже когда Client Hints не поддерживаются.
Техники по определению браузера не так умны, поэтому можно брать строку браузера из HTTP заголовков и таблицу поиска и с их помощью определять возвращаемый медиа тип на основе этих заголовков. Можно переписывать расширения изображения, а можно на каждый вызов изображения возвращать «правильный» тип изображения для всех браузеров, но с «неправильным» расширением. Например, если запрошено изображение foo.jpg, верните лучший медиа тип для браузера, но вызывайте foo.jpg, медиа тип не важен. На сайте Instart Logic мы возвращаем формат webP для бразуеров Chrome и Opera, JPEG-XR для Edge и т.д…. мы не переписываем путь к изображению. Мы просто используем расширение оригинала в имени файла, у нас это jpg. Мы пользуемся тем, что браузеры отрисовывают изображения тех медиа типов, которые они распознают, и не смотрят на расширения (или их отсутствие) в имени файла. В таком случае можно не менять разметку и DOM в JS, а также загружать всего одно изображение на один запрос.
Если вы собираетесь возвращать разные медиа типы на основе поддержки браузера, но с одним и тем же разрешением в имени файла, вам придется хранить правильное изображение на стороне сервера в базе данных, так как вам нужно будет обрабатывать разные версии изображения с одинаковым именем. На стороне клиента нужно было бы запрашивать правильное расширение (если знаете способ лучше или просто другой, дайте мне знать).
Автоматизация процесса по созданию файлов
Лучше всего предоставлять пользователям индивидуально подобранные изображения для индивидуально подобранных объявлений изображений, которые поддерживаются браузером. В предыдущем разделе мы узнали, как передать браузеру, чтобы тот использовал изображение определенного размера и типа на основе его функций. Однако нам все еще нужно создать изображения всех размеров для всех медиа типов с наилучшим уровнем сжатия для каждого отдельного изображения. Вопрос заключается в том, как создать все изображения?
Нам нужно автоматизировать сжатие и изменение размеров изображения во множество форматов, поддерживаемых различными браузерами, устройствами и операционными системами. Лучше всего, чтобы наилучшая степень и уровень сжатия определялись для каждого изображения индивидуально.
Оптимизация изображений может занять много времени на нестатических сайтах, где изображений могут быть тысячи, десятки тысяч и даже миллионы, все разных размеров, разрешений и медиа типов. В программе ImageMagick можно конвертировать изображения в PNG, JPEG, JPEG-2000, GIF, WebP и почти любой формат через командную строку:
1 |
convert myImg.jpg -quality 78 -define webp:lossless=true myImg.webp |
Команда выше сохраняет конвертированную копию изображения myImg.jpg в формате webP с качеством 78%. В программе ImageMagick изображения можно конвертировать и одновременно изменять их размер (или просто менять размер) при помощи флага –resize:
1 |
convert myImg.jpg -quality 78 -resize 50% myImg.webp |
Команда выше создает новый файл, конвертируя JPEG в WebP и сохраняя 78% качества от оригинала, высота и ширина уменьшаются вдвое с сохранением соотношения сторон.
В командной строке можно создавать изображения любого формата и размера. Можно автоматизировать процесс конвертации формата и размеров. Намного сложнее и непрактично правильно определить качество сжатия для каждого изображения. Этот этап обычно нужно прогонять вручную.
В масштабе всего интернета для определения наилучшего качества для всех изображений нужна целая армия людей. Большинство конвертеров и сервисов снижают размер файла за счет снижения качества изображений по одному и тому же коэффициенту или уровню сжатия. К примеру, когда на моих сайтах было мало изображений, я мог вручную сжимать их. Качество менялось от низкого 35% до высокого 88%. Для галерей и других проектов с множеством изображений я использовал Adobe Fireworks для автоматизации сжатия и экспорта, сохраняя все в JPEG с качеством 78%. Как и я, большая часть инструментов по автоматизации сжатия используют одни и те же настройки качества, обычно это около 80%. Я выбрал 78% чисто случайно (немного основываясь на опыте). Волшебного значения качества, которое подойдет под все изображения, нет. Не существует магического уровня сжатия, который сжимает без потерь качества все изображения.
«Правильная» степень сжатия зависит от контента и того, как будет использоваться изображение. Уровень качества экспорта обычно зависит от деталей на изображении. В зависимости от контента подбирается разный уровень для каждого изображения. Зачастую чем больше деталей в изображении, тем ниже качество: пейзаж требует высокого качества под 90, а изображение с множеством деталей будет хорошо смотреться и на уровне ниже 50.
Автоматизировать настройку качества под каждое изображение все-таки можно. Сайт Instart Logic использует computer vision, машинное обучение и конвертер для оптимизации изображений с учетом содержимого, автоматизации процесса создания изображений, оптимизированных под разрешение устройства, браузер и сеть, а также для вычисления оптимального коэффициента сжатия без ущерба для работы пользователя. SmartVision – это алгоритмический подход, использующий машинное обучение для автоматизации адаптивных настроек под каждое изображение, сжимая изображение на максимум без потери качества (исключение составляют только первые несколько изображений, на которых происходит калибровка алгоритма машинного обучения). Продвинутые алгоритмы компьютерного зрения «заглядывают» в контент изображения и максимизируют уровень сжатия без ущерба для работы пользователя на уровне интеллекта. Парвиз Ахаммад объяснил свои алгоритмы для SmartVision намного лучше меня еще в 2014.
Браузеры далеко продвинулись за последние 6 лет, увеличился и средний вес сайтов. Изображения же – главный виновник медленной загрузки, а современные изображения – лишь часть решения. Время, потраченное на оптимизацию изображений, проведено не зря.
Автор: Estelle Weyl
Источник: //calendar.perfplanet.com/
Редакция: Команда webformyself.