Pull to refresh

Оптимизация графики для веба: самое важное

Reading time54 min
Views94K
Original author: Addy Osmani
Автор электронной книги — Эдди Османи, один из руководителей разработки Google Chrome

tl;dr


Cжатие изображений всегда должно быть автоматизировано


Оптимизацию графики обязательно надо автоматизировать. О ней легко забыть, рекомендации меняются, да и сам контент может легко проскользнуть мимо конвейера сборки. Для автоматизации при сборке используйте imagemin или libvips. Есть и много других.

Большинство CDN (например, Akamai) и сторонних решений вроде Cloudinary, imgix, Fastly Image Optimizer, Instart Logic SmartVision и ImageOptim API предлагают комплексные автоматизированные решения для оптимизации изображений.

На чтение статей и настройку конфигурации вы потратите время, которое дороже оплаты их услуг (у Cloudinary есть бесплатный тариф). Но если всё-таки не хотите отдавать работу на аутсорсинг по соображениям стоимости или из-за дополнительной latency, то выбирайте приведённые выше варианты с открытым исходным кодом. Проекты Imageflow или Thumbor предлагают альтернативу на собственном хостинге.

Все должны эффективно сжимать изображения


Как минимум, используйте ImageOptim. Он значительно уменьшает размер при сохранении визуального качества. Есть версии под Windows и Linux.

Более тщательный подход: прогоняйте JPEG-файлы через MozJPEG (для веб-контента приемлемо качество q=80 или ниже) и рассмотрите поддержку Progressive JPEG. Файлы PNG пропускайте через pngquant, а SVG — через SVGO. Явно укажите очистку от метаданных (--strip для pngquant), чтобы избежать раздутия файлов. Вместо сумасшедших гигантских анимированных GIF отдавайте пользователям видео H.264 (или WebM для Chrome, Firefox и Opera)! Если не можете себе это позволить, то хотя бы используйте Giflossy. Когда есть возможность потратить пару циклов CPU, а вам нужно изображение лучшего качества и вы готовы смириться с длительным временем кодирования, то попробуйте Guetzli.

Некоторые браузеры анонсируют поддержку графических форматов через заголовок Accept. Это можно использовать при выборе формата для выдачи: например, формат WebP для браузеров на основе Blink, таких как Chrome, и вариант JPEG/PNG для других браузеров.

Сжатие всегда можно улучшить. Есть инструменты для генерации и выдачи srcset. В браузерах на основе Blink выбор ресурсов автоматизируется с помощью client-hints — и вы сэкономите трафик на пользователях, которые указали в браузере опцию «экономия данных» через подсказку Save-Data.

Чем меньше размер изображений, тем удобнее пользователям — особенно с мобильными телефонами. В этой статье мы рассмотрим способы сжатия графики современными методами с минимальным влиянием на качество.

Содержание



Введение


Графика остаётся главной причиной ожирения веб-страниц


Изображения составляют огромную долю интернет-трафика. Согласно HTTP Archive, 60% объёма веб-страниц — это графика в форматах JPEG, PNG и GIF. По состоянию на июль 2017 года изображения составляли 1,7 МБ на средней веб-странице объёмом 3,0 МБ.

Эксперимент Тэмми Эвертса доказал, что добавление изображений на страницу или увеличение существующих изображений повышает коэффициент конверсии (процент посетителей, которые становятся клиентами — прим. пер.). Так что картинки никуда не денутся — вот почему важно вложиться в эффективную стратегию по их сжатию.


Исследование Soasta/Google от 2016 года показало, что иллюстрации — это второй предиктор конверсии, а у эффективных страниц на 38% меньше картинок

Оптимизация изображений включает ряд мер. Выбор зависит от того, какую потерю качества считать приемлемой.


Оптимизация: выбрать правильный формат, аккуратно сжать и установить приоритеты загрузки разных изображений

Типичная оптимизация включает сжатие, грамотную выдачу изображений на основе размера с помощью тегов <picture>/<img srcset> и изменение размера.


Согласно HTTP Archive, на 95-м процентиле (в кумулятивной функции распределения) каждая картинка поддаётся уменьшению на 30 КБ!

У нас ещё очень много изображений, которые можно оптимизировать.


Бесплатная программа ImageOptim уменьшает размер графики с помощью современных методов сжатия и удаления ненужных метаданных EXIF

Если вы дизайнер, есть ещё плагин ImageOptim для Sketch, который оптимизирует ресурсы при экспорте. Я нашёл, что он экономит массу времени.

Как узнать, нужно ли оптимизировать изображения?


Проведите аудит сайта с помощью WebPageTest.org.


В разделе Compress Images отчёта WebPageTest перечислены картинки, которые можно сжать более эффективно, при этом оценивается потенциальный выигрыш по размеру файлов



Сервис Lighthouse тоже осуществляет аудит производительности, в том числе проводит проверку оптимизации изображений. Он показывает картинки, которые можно сжать сильнее и которые можно поставить в ленивую загрузку.

Начиная с Chrome 60 этот сервис работает в панели аудита Chrome DevTools:


Lighthouse проводит аудит с прицелом на производительность, лучшие практики или прогрессивные функции веб-приложений (на выбор)

Вам могут быть известны другие инструменты аудита, такие как PageSpeed Insights и Website Speed Test от Cloudinary, включающий подробный аудит изображений.

Как выбрать формат?


Как отметил Илья Григорик в своём превосходном руководстве по оптимизации изображений, «правильный формат» сочетает в себе желаемый визуальный результат и функциональные требования. У вас растровая или векторная графика?



Растровая графика кодирует значения каждого пикселя на прямоугольной сетке пикселей. Они не зависят от разрешения или масштаба. С такой графикой хорошо справляются WebP или широко поддерживаемые форматы, такие как JPEG или PNG. Растровая графика используется там, где нужен фотореализм. Guetzli, MozJPEG и другие упомянутые инструменты подходят для растровой графики.

Векторная графика применяет точки, прямые и полигоны для представления изображений с простыми геометрическими фигурами (например, логотипов). Она предлагает высокое разрешение и масштабирование. Для такого варианта лучше подходят форматы вроде SVG.

Выбор неправильного формата дорого вам обойдётся. Менять формат следует с осторожностью, проведя эксперименты с возможной экономией в разных форматах.

Джереми Вагнер в своей лекции осветил компромиссы, которые стоит учитывать при оценке разных форматов в процессе оптимизации.

Скромный JPEG


Вероятно, JPEG — самый популярный в мире формат графики. Как отмечалось ранее, 45% изображений на сайтах в HTTP Archive — это картинки JPEG. Ваш телефон, цифровая камера, старая веб-камера — все они обычно поддерживают данный кодек. Он очень древний, используется аж с 1992 года. За это время проведено огромное количество исследований, как улучшить компрессию JPEG.

JPEG — алгоритм сжатия с потерями, который отбрасывает «лишнюю» информацию для экономии места. Задача состоит в максимальном сохранении визуальной точности с минимизацией размеров файлов.

Какое качество изображений приемлемо в вашем случае?


Форматы вроде JPEG лучше всего подходят для фотографий или изображений с большим количеством цветов. Большинство инструментов оптимизации позволит выбрать приемлемый уровень сжатия: более сильное сжатие уменьшает размер файлов, но может привнести артефакты: гало или блочность.


Видимые артефакты сжатия JPEG нарастают по мере перехода от наилучшего качества к худшему. Заметьте, что показатели качества изображения в разных инструментах могут сильно отличаться

При выборе уровня сжатия следует учитывать, какое качество необходимо для изображений:

  • Самое лучшее: когда качество важнее, чем размер файла. Это может быть связано с тем, что изображение занимает видное место в дизайне или отображается в полном разрешении.
  • Хорошее: когда вы думаете об экономии трафика, но не хотите слишком заметно повлиять на качество картинки. Пользователям всё-таки важно и качество иллюстраций.
  • Низкое: когда вы заботитесь о минимальном трафике и миритесь с деградацией изображения. Такой профиль подходит для сетей с плохим покрытием и тонких каналов.
  • Самое низкое: экономия полосы имеет первостепенное значение. Пользователи согласны на довольно плохое качество ради более быстрой загрузки страниц.

Далее поговорим о режимах сжатия JPEG, которые сильно влияют на результат.

Примечание: возможно, мы иногда переоцениваем качество изображения, которое нужно пользователям. Качество можно рассматривать как отклонение от идеального исходника. Это субъективный показатель.

Режимы сжатия JPEG


В формате JPEG есть ряд различных режимов сжатия. Три популярных: базовый (последовательный), прогрессивный JPEG (PJPEG) и сжатие без потерь.

Чем отличаются базовый (или последовательный) и прогрессивный JPEG?


Базовый JPEG (режим по умолчанию в большинстве редакторов и оптимизаторов) кодирует и декодирует относительно просто: сверху вниз. Когда базовый JPEG загружается по медленному или нестабильному соединению, пользователь сначала увидит верхнюю часть картинки. Режим сжатия JPEG без потерь похож на базовый, только с меньшей степенью сжатия.


Базовый JPEG (baseline JPEG) загружается сверху вниз, а прогрессивный JPEG загружается от размытого до резкого

Прогрессивный JPEG делит изображение на ряд проходов. Первый проход показывает картинку в размытом виде и низком качестве, а последующие проходы постепенно улучшают качество. Каждый проход повышает уровень детализации. В конце концов создаётся полноценное изображение.


Базовый JPEG загружает изображение сверху вниз. PJPEG сначала показывает размытую картинку, а потом повышает разрешение. Пэт Минан разработал интерактивный инструмент для тестирования и изучения прогрессивных файлов JPEG

Оптимизация JPEG без потерь достигается путём удаления EXIF-заголовков от цифровых камер и редакторов, оптимизации таблиц Хаффмана и повторного сканирования изображения. Такие инструменты, как jpegtran, обеспечивают сжатие без потерь, перестраивая сжатые данные без ухудшения качества изображения. jpegrescan, jpegoptim и mozjpeg (которые мы скоро рассмотрим) тоже поддерживают сжатие JPEG без потерь.

Преимущества прогрессивных JPEG


Способность PJPEG показывать превью при загрузке повышает производительность — пользователям кажется, что изображение загружается быстрее по сравнению со стандартной графикой.

На медленных 3G-соединениях это позволяет примерно увидеть картинку, когда получена только часть файла — и принять решение, дожидаться его полной загрузки или нет. Это может оказаться удобнее, чем загрузка изображения сверху вниз, как в базовом JPEG.


В 2015 году Facebook перешёл на PJPEG (для своего приложения iOS) и трафик уменьшился на 10%. Они смогли показать изображение хорошего качества на 15% быстрее, чем раньше, оптимизировав воспринимаемое время загрузки, как показано на рисунке выше

PJPEG может уменьшить размер файла на 2−10% по сравнению с базовым/простым JPEG для изображений более 10 КБ. Более высокий коэффициент сжатия достигается благодаря тому, что на каждом проходе может составляться отдельная таблица Хаффмана. Современные JPEG-кодеры (например, libjpeg-turbo, MozJPEG и др.) используют гибкость PJPEG для лучшего сжатия данных.

Примечание: почему PJPEG сжимает лучше? Потому что блоки базового JPEG кодируются по одному, а в PJPEG коэффициенты дискретного косинусного преобразования из нескольких блоков можно кодировать вместе, что приводит к лучшему сжатию.

Кто использует прогрессивный JPEG в продакшне?


  • Twitter.com выдаёт прогрессивные JPEG с базовым уровнем качества 85%. Они замерили субъективную задержку, воспринимаемую пользователем (время до первого прохода и общее время загрузки), и решили, что PJPEG в целом подходит исходя из качества компрессии, скорости кодирования и декодирования.
  • Facebook выдаёт прогрессивные JPEG в приложении iOS. Это на 10% уменьшило трафик и на 15% ускорило выдачу изображений «хорошего качества».
  • Yelp перешёл на прогрессивный JPEG. Это одна из мер, которая уменьшила размер изображений примерно на 4,5%. Она сократился ещё на 13,8% за счёт MozJPEG.

Многие другие сайты с большим количеством графических файлов, такие как Pinterest, тоже используют прогрессивный JPEG в продакшне.


На сайте Pinterest изображения кодируются только в прогрессивном JPEG. Для пользователей удобнее, когда картинка проявляется постепенно

Недостатки прогрессивного JPEG


Декодирование PJPEG медленнее, чем базового JPEG — иногда втрое медленнее. На десктопных машинах с мощными процессорами это не так важно, как на мобильных устройствах с ограниченными ресурсами. Отображение неполных слоёв требует работы, поскольку вы фактически декодируете изображение несколько раз. Эти множественные проходы съедают циклы CPU.

Также картинки в прогрессивном JPEG не всегда меньше по размеру. Прогрессивное кодирование очень маленьких изображений (например, миниатюр для предпросмотра) может увеличить их размер. И для таких картинок рендеринг в несколько проходов вообще имеет мало смысла.

Так что перед выбором PJPEG желательно поэкспериментировать и найти правильный баланс между размером файла, сетевой задержкой и использованием CPU.

Примечание: на мобильных устройствах может поддерживаться аппаратное декодирование PJPEG (и всех JPEG). Это не снижает потребление памяти, но уменьшает нагрузку на процессор. Не во всех смартфонах Android есть аппаратное ускорение, но в устройствах высокого класса и в устройствах iOS оно есть.

Некоторые пользователи могут считать прогрессивную загрузку недостатком, так как она мешает понять, когда завершилась загрузка изображения. Попробуйте оценить, как к этому относится ваша аудитория.

Как кодировать файлы в формате прогрессивного JPEG?


Инструменты и библиотеки вроде ImageMagick, libjpeg, jpegtran, jpeg-recompress и imagemin поддерживают прогрессивный JPEG. Если у вас уже налажен конвейер по оптимизации, то велика вероятность, что изменение способа кодирования JPEG не станет проблемой:

const gulp = require('gulp');
const imagemin = require('gulp-imagemin');

gulp.task('images', function () {
    return gulp.src('images/*.jpg')
        .pipe(imagemin({
            progressive: true
        }))
        .pipe(gulp.dest('dist'));       
});

Большинство редакторов по умолчанию сохраняют в базовый JPEG.


Большинство редакторов по умолчанию сохраняют в базовый JPEG, но это можно изменить в настройках. В Photoshop нужно выбрать команду «Файл» → «Экспорт» → «Сохранить для веба», а там указать формат прогрессивного JPEG. Sketch тоже поддерживает экспорт Progressive JPEG путём установки флажка в меню экспорта JPG

Цветовая субдискретизация


Наши глаза хуже замечают потерю цветности, чем яркости. Цветовая субдискретизация (chroma subsampling) — вид компрессии, снижающий точность цветопередачи за счёт яркости (luma). Это уменьшает размер файла до 15−17%, не влияя заметно на качество изображения. Субдискретизация также уменьшает использование памяти.



Контраст отвечает за резкость на картинке, поэтому luma очень важна. На чёрно-белых фотографиях нет цвета, но благодаря яркости они выглядят такими же детальными, как цветные аналоги. Цветность меньше влияет на зрительное восприятие.


JPEG поддерживает различные типы подвыборки: отсутствие подвыборки, горизонтальная, горизонтальная+вертикальная. Здесь иллюстрация из статьи «JPEG для крабов» Фредерика Кайзера

При обсуждении подвыборки обычно приводят ряд распространённых примеров: 4:4:4, 4:2:2 и 4:2:0. Что они собой представляют? Предположим, что подвыборка имеет формат A:B:C. Здесь A — количество пикселей в строке, для JPEG это обычно 4, B — количество цветов в первой строке, а C — количество цветов во второй.

  • В 4:4:4 нет сжатия, цвет и яркость передаются полностью.
  • В 4:2:2 половинный сэмплинг по горизонтали и полный по вертикали.
  • В 4:2:0 используются цвета из половины пикселей первой строки.

Примечание: jpegtran и cjpeg поддерживают отдельную конфигурацию яркости и цветности через флаг -sample (например, -sample 2x1). Некоторые общие правила: субдискретизация (-sample 2x2) отлично подходит для фотографий. Её лучше отключить (-sample 1x1) для скриншотов, баннеров и кнопок. Наконец, 2x1 на тот случай, если нет уверенности, какой вариант использовать.

Уменьшив количество пикселей, можно значительно уменьшить размер цветовых компонентов, в конечном счете уменьшив размер файла.


Варианты цветовой субдискретизации для JPEG с качеством 80

Цветовая субдискретизация полезна для большинства изображений, хотя есть явные исключения: лучше не использовать её там, где цветовая детализация столь же важна, как яркость (например, медицинские снимки).

Пострадают и картинки с изображением шрифтов. Чёткие края сложнее сжать с помощью JPEG, поскольку он разработан для лучшей обработки фотографических сцен с более мягкими переходами.


В работе с текстом учебник «Изучение JPEG» рекомендует придерживаться субдискретизации 4:4:4 (1×1)

Кстати: в спецификациях JPEG не указан точный метод цветовой субдискретизации, поэтому разные кодеры/декодеры поступают по-разному. MozJPEG и libjpeg-turbo используют один метод, а более старые версии libjpeg — другой, который добавляет артефактов.

Примечание: Photoshop автоматически выбирает цветовую субдискретизацию при «сохранении для веба». Если качество установлено в диапазоне 51−100, то субдискретизация не используется (4:4:4). Когда качество ниже, устанавливается 4:2:0. Это одна из причин, почему размер файла резко уменьшается при переключении качества с 51 на 50.

Примечание: в обсуждении субдискретизации часто упоминается термин YCbCr. Это модель цветового пространства RGB с гамма-коррекцией. Y — это яркость с гамма-коррекцией, Cb — компонент chroma синего цвета, а Cr — красного. Если посмотреть ExifData, вы увидите YCbCr рядом с уровнями выборки.

Дополнительные сведения см. в статье «Почему вы не используете цветовую субдискретизацию?»

Улучшенный JPEG


Каково текущее состояние с форматами JPEG в интернете?


tl;dr: поддержка в браузерах сильно отличается. Если использовать современные разработки, то часто придётся выдавать разным браузерам разные форматы.


Различные современные форматы (и оптимизаторы) показывают качество сжатия при целевом размере файла 26 КБ. Качество сравнивается инструментами SSIM (структурное сходство) и Butteraugli, которые мы более подробно рассмотрим позже.

  • JPEG 2000 (2000) — улучшение сжатия за счёт замены дискретного косинусного преобразования на вейвлеты. Поддержка в браузерах: десктопный Safari и iOS.
  • JPEG XR (2009) — альтернатива JPEG и JPEG 2000, поддерживающая HDR и широкие цветовые гаммы. Создаёт файлы меньшего размера, чем JPEG, со слегка с меньшей скоростью кодирования/декодирования. Поддержка в браузерах: Edge, IE.
  • WebP (2010) — основанный на прогнозировании блоков формат от Google поддерживает сжатие с потерями и без потерь. Обеспечивает лучшее сжатие, чем JPEG, и поддерживает прозрачность, как PNG. Не хватает настройки цветовой субдискретизации и прогрессивной загрузки. Скорость декодирования ниже, чем у JPEG. Поддержка в браузерах: Chrome, Opera. Экспериментальная поддержка в Safari и Firefox.
  • FLIF (2015) — формат сжатия без потерь, превосходящий PNG, WebP без потерь, BPG без потерь и JPEG 2000 без потерь по коэффициенту сжатия. Поддержка в браузерах: нет, но есть JS-декодер.
  • HEIF и BPG. С точки зрения сжатия они одинаковы, но поставляются в разных обёртках:
  • BPG (2015) — замена JPEG более эффективным сжатием на основе HEVC (High Efficiency Video Coding). Кажется, обеспечивает меньший размер файлов по сравнению с MozJPEG и WebP. Вряд ли получит широкую поддержку из-за проблем с лицензированием. Поддержка в браузерах: нет, но есть JS-декодер.
  • HEIF (2015) — формат для изображений и последовательностей изображений, закодированных HEVC с межкадровым предсказанием. Apple анонсировала на WWDC, что будет изучать переход c JPEG на HEIF в операционной системе iOS, что даст уменьшение размера файлов до двух раз. Поддержка в браузерах: нет на момент написания статьи. Должна появиться в десктопном Safari и iOS 11.

Если вам нравится воспринимать информацию в графическом виде, можете оценить один из этих инструментов визуального сравнения для некоторых из вышеперечисленных форматов.

Таким образом, поддержка в браузерах сильно отличается. Чтобы использовать любой из вышеперечисленных форматов, вероятно, придётся выдавать разные копии каждому из целевых браузеров. Мы в Google видим определённые перспективы WebP, поэтому вскоре разберём подробнее этот формат.

Вы также можете выдавать разные форматы (например, WebP, JPEG 2000) с одним и тем же расширением .jpg (или любым другим) поскольку браузер может выбрать content-type для рендеринга независимо от расширения. Это позволяет указать content-type на стороне сервера, вообще не меняя HTML-документ. Сервисы вроде Instart Logic используют такой подход.

Далее поговорим о ситуациях, когда нельзя выдавать изображения в разных форматах: здесь помогут JPEG-оптимизаторы.

JPEG-оптимизаторы


Современные кодеки JPEG пытаются уменьшить размер файлов JPEG, максимально сохраняя качество и совместимость с существующими браузерами и приложениями. Они избавляют от необходимости использовать новые форматы изображений и вносить изменения в экосистему. Два таких энкодера — MozJPEG и Guetzli.

tl;dr: Какой JPEG-кодек с оптимизацией использовать?

  • Большинство файлов: MozJPEG
  • Если важно качество и вы согласны на длительное кодирование: Guetzli
  • Если нужна конфигурируемость:

Что такое MozJPEG?


Mozilla предлагает модернизированный JPEG-кодер — MozJPEG. По заявлению разработчиков, он уменьшает размер файлов JPEG до 10%. Файлы, сжатые MozJPEG, открываются во всех браузерах, а среди поддерживаемых функций — прогрессивное сканирование, треллис-квантование (удаление деталей, которые хуже всего сжимаются) и несколько продвинутых шаблонов таблиц квантования, которые помогают создавать более гладкие изображения High-DPI (хотя это возможно с ImageMagick, если вы готовы пробираться через дебри XML-конфигурации).

MozJPEG поддерживается в ImageOptim и для него есть относительно надёжный настраиваемый плагин imagemin. Вот пример реализации с помощью Gulp:

const gulp = require('gulp');
const imagemin = require('gulp-imagemin');
const imageminMozjpeg = require('imagemin-mozjpeg');

gulp.task('mozjpeg', () =>
    gulp.src('src/*.jpg')
    .pipe(imagemin([imageminMozjpeg({
        quality: 85
    })]))
    .pipe(gulp.dest('dist'))
);




MozJPEG: сравнение размера файлов и оценок визуального сходства на разном качестве

Для вычисления оценок SSIM (структурного сходства с исходным изображением) я использовал jpeg-compress из проекта jpeg-archive.

По моему опыту, MozJPEG — хороший вариант сжатия изображений для интернета с высоким качеством при одновременном уменьшении размера файла. Для изображений малого и среднего размера MozJPEG (с качеством 80−85) уменьшает файлы на 30−40% с сохранением приемлемого SSIM и улучшением на 5−6% по jpeg-turbo. Он кодирует медленнее базового JPEG, но разница не критична.

Примечание: если вам нужен инструмент, поддерживающий MozJPEG с дополнительной конфигурацией и некоторыми бесплатными утилитами для сравнения изображений, посмотрите на jpeg-recompress. Автор книги «Веб-производительность в действии» Джереми Вагнер с успехом использовал программу в такой конфигурации.

Что такое Guetzli?


Guetzli — многообещающий, но очень медленный, перцептивный JPEG-кодек от Google. Он пытается найти самый маленький JPEG, перцептивно неотличимый от оригинала. Кодек выполняет ряд экспериментов, предлагая варианты для сравнения, и учитывает психовизуальную ошибку каждого варианта. В качестве конечного результата выбирается вариант с наивысшей оценкой.

Для измерения различия между изображениями Guetzli применяет Butteraugli — модель на основе человеческого восприятия (обсуждается ниже). Guetzli учитывает некоторые свойства человеческого зрения, которые не принимаются в расчёт другими кодеками JPEG. Например, существует зависимость между количеством видимого зелёного света и чувствительностью к синему, поэтому изменения синего цвета около зелёного можно кодировать менее точно.

Примечание: Размер файла намного сильнее зависит от выбора уровня кодирования, чем от выбора кодека. Между низким и высоким уровнями качества в формате JPEG намного, намного бóльшая разница, чем при смене кодека. Очень важно указать минимально приемлемый уровень качества. Обязательно обращайте внимание на этот показатель, чтобы он не оказался слишком высоким.

Guetzli заявляет о разнице в размере файлов 20−30% без уменьшения оценки Butteraugli по сравнению с другими компрессорами. Большой недостаток Guetzli в его чрезвычайной медлительности, так что в настоящее время он подходит только для статического контента. В README указан большой объём потребляемой памяти: кодирование требует около 1 минуты и 200 МБ RAM на мегапиксель. На GitHub есть хороший тред с обсуждением реального опыта работы с Guetzli. Кодек идеально подходит для оптимизации изображений при сборке статического сайта, но в меньшей степени пригоден для запуска по требованию.

Инструменты вроде ImageOptim поддерживают оптимизацию Guetzli (в последних версиях).

const gulp = require('gulp');
const imagemin = require('gulp-imagemin');
const imageminGuetzli = require('imagemin-guetzli');

gulp.task('guetzli', () =>
    gulp.src('src/*.jpg')
    .pipe(imagemin([
        imageminGuetzli({
            quality: 85
        })
    ]))
    .pipe(gulp.dest('dist'))

);



Кодирование Guetzli изображений 3000×3000 пикселей с разными уровнями заняло почти семь минут. Это имеет смысл для архивного хранения фотографий с высоким разрешением.


Guetzli: сравнение размеров файлов и оценки визуального сходства на разном качестве

Примечание: рекомендуется запускать Guetzli на высококачественных изображениях (например, несжатых исходных изображениях, PNG или JPEG с качеством около 100%). Хотя эффект есть и на других изображениях (например, JPEG качества 84 или ниже), но результаты хуже.

Guetzli тратит очень (очень) много времени и заставит по полной раскрутиться кулер CPU, но оно того стоит. Я видел ряд примеров, когда размер файлов уменьшался на 40% при сохранении визуальной точности. Это делает его идеальным выбором для архивирования фотографий. На изображениях малого и среднего размера тоже есть некоторая экономия (в диапазоне 10−15 КБ), но не настолько значительная. При сжатии совсем маленьких изображений Guetzli может привнести «жидкоподобные» искажения.

Для разнообразия вариантов использования вас может заинтересовать сравнение Guetzli с автоматическим сжатием Cloudinary в исследовании Эрика Портиса.

Сравнение MozJPEG и Guetzli


Сложно сравнивать разные кодеки JPEG: необходимо оценить и качество, и точность сжатого изображения, а не только размер. Как отмечает эксперт по сжатию изображений Корнель Лесински, бенчмарк только одного, а не обоих аспектов, может привести к неверным выводам.

Как выглядят Guetzli и MozJPEG в сравнении? Подход Корнеля:

  • Guetzli подходит для изображений более высокого качества (оптимальная оценка butteraugli считается для q=90+, а у MozJPEG — около q=75)
  • Guetzli намного медленнее (оба производят стандартные JPEG, поэтому декодирование одинаково быстрое, как обычно)
  • MozJPEG не выбирает автоматически настройку качества, но вы можете найти оптимальное качество с помощью внешнего инструмента, например, jpeg-archive

Существует ряд методов определения визуального или перцептивного сходства сжатых изображений с исходником. В исследованиях часто используется SSIM (структурное сходство). Однако Guetzli оптимизирован для Butteraugli.

Butteraugli


Система Butteraugli определяет момент, когда человек начинает замечать разницу (психовизуальное сходство) между двумя изображениями. Butteraugli не только даёт оценку, но и составляет пространственную карту уровня различий. В то время как SSIM суммирует все ошибки, Butteraugli ищет максимальные.


В этом примере Butteraugli ищет минимальный порог качества JPEG, чтобы пользователь не заметил визуальной разницы между изображениями. Это позволило уменьшить размер файла на 65%

На практике вы определяете уровень визуального качества, а затем запускаете несколько стратегий оптимизации изображений, глядя на оценки Butteraugli, прежде чем выбрать результат, который соответствует оптимальному балансу размера файла и уровня сжатия.


Мне потребовалось около 30 минут для локальной настройки Butteraugli после установки Bazel и сборки исходников C++ для корректной компиляции на Mac. Его использование относительно простое: укажите два изображения для сравнения (исходная и сжатая версия) — и получите оценку

Чем Butteraugli отличается от других способов оценки визуального сходства?


Один из разработчиков Guetzli говорит, что Guetzli лучше по оценке Butteraugli, хуже по SSIM, а MozJPEG примерно одинаково хорош по обеим метрикам. Это стратегию я использую для оптимизации изображений. Я запускаю Butteraugli и модуль Node вроде img-ssim для сравнения оценок SSIM до/после Guetzli и MozJPEG.

Объединение энкодеров?


Как показала практика, сочетание Guetzli и MozJPEG без потерь (jpegtran, а не cjpeg, чтобы не отбрасывать работу, проделанную Guetzli) позволяет дополнительно уменьшить размер файла на 10−15% (55% в целом) с весьма незначительным снижением оценки SSIM. Это требует проверки и анализа, но другие специалисты вроде Арии Хидаята попробовали — и получили такой же многообещающий результат.

MozJPEG — удобный кодек для новичков, который сравнительно быстро сжимает файлы для веба и обеспечивает хорошее качество изображения. В то же время Guetzli ресурсоёмок и лучше всего работает на больших, высококачественных изображениях: этот вариант я бы рекомендовал продвинутым и профессиональным пользователям.

Что такое WebP?


WebP — последний графический формат от Google, который стремится уменьшить размеры файлов при сжатии без потерь и с потерями, обеспечивая приемлемое визуальное качество. Поддерживает альфа-канал (прозрачность) и анимацию.

WebP совершенствуется: за прошлый год он прибавил несколько процентов в сжатии без потерь и с потерями, по скорости кодирования стал вдвое быстрее, а скорость декодирования увеличилась на 10%. WebP — не универсальный инструмент, но его популярность растёт. Давайте рассмотрим, почему.


WebP: сравнение размеров файлов и оценки визуального сходства на разных уровнях качества

Как работает WebP?


Cжатие с потерями


Разработчики говорят, что при сжатии с потерями с использованием кодека VP8 или VP9 файлы уменьшаются в среднем на 25−34% по сравнению с JPEG.

В диапазоне низкого качества (0−50) у WebP большое преимущество перед JPEG, поскольку он размывает уродливые артефакты блочности. Настройка среднего качества (-m 4 -q 75) — установленный по умолчанию баланс скорости и размера файла. В диапазоне высокого качества (80−99) преимущества WebP минимальны. WebP рекомендуется там, где скорость важнее качества.

Сжатие без потерь


Файлы WebP со сжатием без потерь на 26% меньше файлов PNG. Время загрузки по сравнению с PNG уменьшается на 3%. Однако в интернете сжатие без потерь обычно не используется. Такой вариант лучше подойдёт для архивного хранения.

Прозрачность


У WebP есть 8-битный канал прозрачности со сжатием без потерь всего на 22% больше по байтам, чем у PNG. Он также поддерживает прозрачность RGB с потерями, это уникальная особенность WebP.

Метаданные


Формат WebP поддерживает метаданные фотографий EXIF и цифровых документов XMP, а также содержит цветовой профиль ICC.

WebP обеспечивает лучшее сжатие за счёт большей загрузки CPU. Ещё в 2013 году сжатие WebP было примерно в 10 раз медленнее, чем у JPEG, но теперь разница не так значительна (некоторые изображения могут сжиматься вдвое медленнее). Для статических изображений, которые обрабатываются в процессе сборки, это не должно быть большой проблемой. Динамически генерируемые изображения, вероятно, вызовут заметное использование CPU, с которым придётся считаться.

Примечание: настройки качества WebP с потерями не соответствуют настройкам JPEG. Например, JPEG с качеством 70% будет сильно отличаться от изображения WebP с качеством 70%, потому что WebP достигает меньших размеров файлов, отбрасывая больше данных.

Кто использует WebP в продакшне?


Много больших компаний используют WebP в продакшне для снижения расходов и увеличения скорости загрузки страницы.

Google сообщил об экономии 30−35% на WebP по сравнению с другими схемами сжатия с потерями. Google выдаёт 43 миллиарда изображений в день, 26% из которых сжаты без потерь. Это много запросов и значительная экономия. Несомненно, она ещё увеличится, когда браузеры улучшат поддержку WebP. Google использует этот формат на Google Play, YouTube и других сайтах.

Netflix, Amazon, Quora, Yahoo, Walmart, Ebay, The Guardian, Fortune и USA Today сжимают и выдают изображения WebP для браузеров, которые его поддерживают. Издатель VoxMedia на 1−3 секунды уменьшил время загрузки страниц The Verge, перейдя на WebP для пользователей Chrome. Сайт 500px зафиксировал уменьшение размеров файлов в среднем на 25% с аналогичным или лучшим качеством.

Кроме вышеперечисленных, WebP используют и другие компании.


Использование WebP в Google: 43 миллиарда картинок WebP ежедневно выдаются на YouTube, Google Play, Chrome Data Saver и G+

Как работает кодирование WebP?


Для статических изображений WebP — альтернатива JPEG. В кодировании с потерями три ключевых этапа:

Macro-blocking — разделение изображения на (макро) блоки по 16×16 пикселей яркости и на блоки по 8×8 пикселей цветности. Это похоже на то, как JPEG преобразует цветовое пространство, разбивая его на блоки и понижая количество пикселей на каналах цветности.



Прогнозирование — для каждого подблока 4×4 составляется модель прогнозирования, которая эффективно выполняет фильтрацию. Её определяют два набора пикселей вокруг блока: A (строка непосредственно сверху) и L (столбец слева). С помощью этих двух наборов энкодер заполняет пикселями тестовый блок 4×4 и определяет, какие значения ближе всего к исходному блоку. Кольт Маканлис более подробно рассказывает об этом в статье о том, как работает WebP в режиме сжатия с потерями.



Дискретное косинусное преобразование (DCT) применяется в несколько этапов, как в JPEG. Ключевое отличие — использование арифметического сжатия, а не алгоритма Хаффмана, как в JPEG.

Для дополнительной информации рекомендую статью «Методы сжатия WebP» с сайта Google Developer.

Поддержка браузерами WebP


Не все браузеры поддерживают WebP, но по данным CanIUse.com, глобальная поддержка составляет около 74%. Chrome и Opera поддерживают формат. Safari, Edge и Firefox экспериментируют, но пока не реализовали поддержку в официальных версиях. Из-за этого выдача WebP зачастую зависит от веб-разработчика. Подробнее об этом позже.

Вот основные браузеры и информация о поддержке каждым из них:

  • Chrome: полная поддержка с версии 23
  • Chrome для Android: начиная с Chrome 50
  • Android: с 4.2
  • Opera: с 12.1
  • Opera Mini: все версии
  • Firefox: некоторая бета-поддержка
  • Edge: некоторая бета-поддержка
  • Internet Explorer: нет
  • Safari: некоторая бета-поддержка

WebP не лишён недостатков. В нём отсутствуют опции цветового пространства с полным разрешением и не поддерживается прогрессивное декодирование. Тем не менее, для WebP создан приличный инструментарий, а поддержки браузеров вполне хватает, чтобы рассматривать выдачу WebP как один из вариантов.

Как конвертировать изображения в WebP?


Несколько коммерческих и свободных редакторов поддерживают WebP. Одно из самых полезных приложений — XnConvert: это бесплатный кросс-платформенный пакетный конвертер.

Примечание: важно не допускать преобразования в WebP картинок JPEG низкого или среднего качества. Это распространённая ошибка, в результате которой генерируются изображения WebP с артефактами сжатия JPEG. Это снижает эффективность WebP, поскольку ему приходится сохранять и изображение, и искажения JPEG, что приводит к двойной потере качества. Загружайте в конвертер файл максимального качества, желательно оригинал.

XnConvert


XnConvert производит пакетную обработку изображений более чем 500 форматов. Вы можете объединить разными способами более 80 отдельных действий для преобразования или редактирования изображений.


XnConvert поддерживает пакетную оптимизацию изображений, выполняя прямое преобразование из исходных файлов в WebP и другие форматы. Кроме сжатия, XnConvert умеет удалять метаданные, обрезать картинки, настраивать глубину цвета и выполнять другие преобразования

Некоторые параметры, перечисленные на веб-сайте xnview:

  • Метаданные: редактирование
  • Преобразования: поворот, обрезание, изменение размера
  • Регулировки: яркость, контраст, насыщенность
  • Фильтры: размытие, рельеф, резкость
  • Эффекты: маски, водяные знаки, виньетирование (частичное затемнение)

Результаты операций можно экспортировать примерно в 70 различных форматов файлов, включая WebP. XnConvert — бесплатная программа под Linux, Mac и Windows. Это отличный вариант, особенно для малого бизнеса.

Модули Node


Imagemin — популярный модуль сжатия изображений, у которого есть расширение для преобразования в WebP (imagemin-webp). Поддерживается сжатие с потерями и без потерь.

Для установки imagemin и imagemin-webp запустите:

> npm install --save imagemin imagemin-webp

Затем можем прописать require() в обоих модулях и запустить их на любых изображениях (например, JPEG) в каталоге проекта. Ниже мы используем кодирование с потерями с качеством энкодера WebP 60:

const imagemin = require('imagemin');
const imageminWebp = require('imagemin-webp');

imagemin(['images/*.{jpg}'], 'images', {
    use: [
        imageminWebp({quality: 60})
    ]
}).then(() => {
    console.log(‘Images optimized’);
});

Как и в JPEG, можно заметить артефакты сжатия на конечной картинке. Оцените сами, какой уровень сжатия адекватен для ваших файлов. Imagemin-webp также можно использовать для кодирования изображений WebP без потери качества (с поддержкой 24-битного цвета и полной прозрачности), указав параметр lossless: true:

const imagemin = require('imagemin');
const imageminWebp = require('imagemin-webp');

imagemin(['images/*.{jpg,png}'], 'build/images', {
    use: [
        imageminWebp({lossless: true})
    ]
}).then(() => {
    console.log(‘Images optimized’);
});

Плагин WebP для Gulp от Синдре Сорхуса сделан на базе imagemin-webp, есть ещё загрузчик WebP для WebPack. Плагин Gulp понимает все опции расширения imagemin:

const gulp = require('gulp');
const webp = require('gulp-webp');

gulp.task('webp', () =>
    gulp.src('src/*.jpg')
    .pipe(webp({
        quality: 80,
        preset: 'photo',
        method: 6
    }))
    .pipe(gulp.dest('dist'))
);

Или сжатие без потерь:

const gulp = require('gulp');
const webp = require('gulp-webp');

gulp.task('webp-lossless', () =>
    gulp.src('src/*.jpg')
    .pipe(webp({
        lossless: true
    }))
    .pipe(gulp.dest('dist'))
);

Пакетная оптимизация изображений с помощью Bash


XNConvert поддерживает пакетное сжатие, но всё можно сделать из командной строки.

Пакетная конвертация изображений в формат WebP с помощью cwebp:

find ./ -type f -name '*.jpg' -exec cwebp -q 70 {} -o {}.webp \;

Оптимизация кодеком MozJPEG с использованием jpeg-recompress:

find ./ -type f -name '*.jpg' -exec jpeg-recompress {} {} \;

и обрезка SVG с помощью программы svgo (которую мы рассмотрим позже):

find ./ -type f -name '*.svg' -exec svgo {} \;

Джереми Вагнер написал более полную статью по оптимизации изображений в Bash и ещё одну — о распараллеливании этой задачи.

Другие приложения для обработки и редактирования WebP


  • Leptonica — целый веб-сайт свободных приложений для обработки и анализа изображений.
  • Sketch поддерживает сохранение в WebP.
  • GIMP — бесплатная альтернатива Photoshop с открытым исходным кодом.
  • ImageMagick — создание, компоновка, преобразование и редактирование растровой графики. Бесплатный, работает из командной строки.
  • Pixelmator — коммерческий редактор изображений для Mac.
  • Photoshop WebP Plugin — бесплатный плагин от Google. Импорт и экспорт изображений в Photoshop.

Для Android вы можете конвертировать существующие BMP, JPG, PNG и статические GIF-изображения в формат WebP с помощью Android Studio. Дополнительные сведения см. в разделе «Создание изображений WebP с помощью Android Studio».

Как просмотреть изображения WebP на моей ОС?


Хотя изображения WebP всегда открываются в браузере на движке Blink (Chrome, Opera, Brave), их можно просматривать непосредственно из ОС с помощью надстройки для Mac или Windows.

Несколько лет назад Facebook экспериментировал с WebP и заметил проблему: некоторые пользователи сохраняли картинки на диск, а потом не могли их открыть. Здесь три ключевые проблемы:

  • После сохранения не удаётся просмотреть файлы WebP локально. Это исправлено в Chrome, который теперь регистрирует на себя расширение .webp.
  • После сохранения изображение отправляется по электронной почте человеку, у которого нет Chrome. Facebook решил проблему, внедрив большую кнопку «Скачать», по которой отдаёт JPEG.
  • Копирование URL картинки с последующей публикацией в интернете решается путём согласования content-type.

У ваших пользователей такие проблемы могут не проявиться, но это интересная заметка на полях. К счастью, сегодня существуют утилиты для просмотра WebP под разные ОС.

На Mac попробуйте плагин Quick Look для WebP (qlImageSize). Он неплохо работает:



Под Windows можно загрузить пакет кодеков WebP, который добавляет опцию просмотра WebP в File Explorer и Windows Photo Viewer.

Как отдавать WebP?


Браузеры без поддержки WebP не покажут никакой картинки. Чтобы избежать этого, есть несколько стратегий.


Панель Chrome DevTools Network с выделением файлов типа WebP, которые отдаются в браузеры на движке Blink


Play Store отдаёт WebP браузерам на Blink и JPEG остальным, таких как Firefox

Вот некоторые варианты доставки изображений WebP пользователям:

Использовать .htaccess для выдачи копий WebP


Вот как использовать .htaccess для выдачи файлов WebP в поддерживаемых браузерах, если на сервере есть webp-версия файла JPEG/PNG.

Винсент Орбак рекомендовал такой подход:

Браузеры могут явно сигнализировать о поддержке WebP через заголовок Accept. В этом случае вы можете отдать с сервера WebP-версию изображения. Но это не всегда возможно (например, для статических хостов, вроде страниц GitHub или S3), поэтому обязательно проверьте, прежде чем рассматривать эту опцию.

Ниже приведён пример файла .htaccess для веб-сервера Apache:

<IfModule mod_rewrite.c>

  RewriteEngine On

  # Check if browser support WebP images
  RewriteCond %{HTTP_ACCEPT} image/webp

  # Check if WebP replacement image exists
  RewriteCond %{DOCUMENT_ROOT}/$1.webp -f

  # Serve WebP image instead
  RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=accept:1]

</IfModule>

<IfModule mod_headers.c>

    Header append Vary Accept env=REDIRECT_accept

</IfModule>

AddType  image/webp .webp

Если есть проблемы с отображением графики WebP, убедитесь, что на сервере включен MIME-тип image/webp.

На Apache добавьте в файл .htaccess следующий код:

AddType image/webp .webp

На Nginx добавьте в файл mime.types следующий код:

image/webp webp;

Примечание: Винсент Orback приводит образец htaccess для выдачи WebP, а Илья Григорик поддерживает коллекцию скриптов конфигурации для выдачи WebP, которые могут быть полезны.

Использование тега <picture>


Браузер сам способен выбирать формат изображения с помощью тега <picture>. Внутри <picture> указано множество элементов <source>, с одним тегом <img> у каждого, где фактически содержится изображение. Браузер просматривает <source> и запрашивает первый подходящий. Если тег <picture> не поддерживается, то осуществляется рендеринг <div> с использованием тега <img>.

Примечание: будьте осторожны с порядком элементов <source>. Не размещайте источники image/webp после устаревших форматов, а ставьте перед ними. Вы также можете разместить изображения по возрастанию объёма файла, если у них одинаковый размер в пикселях (когда не используется атрибут media). Обычно получается такой же порядок, как при указании сначала более новых форматов.

Вот некоторые примеры HTML:

<picture>
  <source srcset="/path/to/image.webp" type="image/webp">
  <img src="/path/to/image.jpg" alt="">
</picture>

<picture>   
    <source srcset='paul_irish.jxr' type='image/vnd.ms-photo'>  
    <source srcset='paul_irish.jp2' type='image/jp2'>
    <source srcset='paul_irish.webp' type='image/webp'>
    <img src='paul_irish.jpg' alt='paul'>
</picture>

<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 src="photo.jpg" alt="My beautiful face">
</picture>

Автоматическое преобразование в WebP на стороне CDN


Некоторые CDN поддерживают автоматическое преобразование и выдачу WebP по запросу клиента, когда это возможно. Проверьте свой CDN, есть ли у них поддержка. Возможно, проблема очень просто решается.

Поддержка WordPress


Jetpack: популярный плагин WordPress, включает в себя CDN-сервис изображений под названием Photon с поддержкой WebP. Он включён в бесплатную версию Jetpack, что очень практично и полезно. Недостаток в том, что Photon автоматически изменяет размеры изображения, помещает строку запроса в URL, а для каждого изображения выполняется дополнительный запрос к DNS.

Cache Enabler и Optimizer: если вы используете WordPress, есть как минимум один вариант с открытым исходным кодом. В меню плагина Cache Enabler есть флажок для кэширования и выдачи изображений WebP, если браузер пользователя их поддерживает. Это упрощает работу с WebP. Здесь тоже недостаток: Cache Enabler требует использования родственной программы Optimizer, за которую взимают ежегодную плату. Это не очень характерно для решений с открытым исходным кодом.

Short Pixel: другой вариант оптимизатора для Cache Enabler, тоже платный. По функциональности Short Pixel очень похож на упомянутый Optimizer. Позволяется бесплатно оптимизировать до 100 фотографий в месяц.

Сжатие GIF-анимаций и почему <video> лучше


Анимированные GIF по-прежнему широко используются, несмотря на их узкую специализацию. Хотя все, от социальных сетей до популярных медиа-сайтов, обильно использую GIF-анимацию, этот формат никогда не предназначался для видео или анимации. На самом деле спецификация GIF89a явно указывает, что «GIF не предназначен служить платформой для анимации». Количество цветов, количество кадров и пропорции — всё это влияет на размер анимированного GIF. Замена на видеоформат даёт максимальную экономию.


Сравнение размеров GIF-анимации и видео в эквивалентном качестве

Выдача того же видео в формате MP4 сокращает размер файла на 80% или больше. Кроме того, что файлы GIF впустую тратят трафик, они дольше загружаются, содержат меньше цветов и обычно выглядят не очень приятно. Возможно, вы обратили внимание, что загруженные в Twitter анимации GIF работают там лучше, чем на других сайтах. Это потому что анимированные GIF в Twitter на самом деле не являются GIF-файлами. Чтобы улучшить качество и уменьшить трафик, Twitter автоматически преобразует их в видео. Аналогично, Imgur при загрузке конвертирует GIF в MP4.

Почему GIF-файлы во много раз больше про размеру? Потому что они хранят каждый кадр как GIF-изображение без потерь — да, без потерь. Плохое качество GIF вызвано не сжатием, а палитрой в 256 цветов. Формат не анализирует соседние кадры для сжатия, в отличие от видеокодеков вроде H.264. Видео MP4 хранит каждый ключевой кадр как JPEG с потерями, отбрасывая часть исходных данных для достижения лучшего сжатия.

Если можете переключиться на видео


  • Используйте ffmpeg для преобразования анимированных GIF (или исходных файлов) в формат MP4 (H.264). Я запускаю такой однострочник из Rigor:

    ffmpeg -i animated.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)2:trunc(ih/2)2" video.mp4
  • ImageOptim API тоже поддерживает преобразование анимированных GIF в WebM/H.264 и удаляет сглаживание GIF, что ещё больше повышает сжатие

Если приходится использовать анимированные GIF


  • Инструменты вроде Gifsicle удаляют метаданные, неиспользуемые цвета палитры и минимизируют изменения между кадрами.
  • Рассмотрим кодирование GIF с потерями. Giflossy — форк Gifsicle, который поддерживает флаг -lossy и сжимает анимацию на 60−65%. На его основе сделан хороший инструмент Gifify. Неанимированные GIF преобразуйте в формат PNG или WebP.

Для получения дополнительной информации см. «Книгу GIF» от Rigor.

Оптимизация SVG


Минимизировать файлы SVG — значит удалить всё лишнее. Как правило, SVG из редактора содержит много избыточной информации (метаданные, комментарии, скрытые слои и так далее). Зачастую её можно безопасно удалить или свести к минимуму, не влияя на визуальный результат.


В сервисе SVGOMG от Джейка Арчибальда можно выбрать разные способы оптимизации с мгновенным просмотром результата

Некоторые общие правила оптимизации SVG (SVGO)


  • Минифицируйте файлы SVG и сжимайте в gzip, ведь SVG — это просто текстовые ресурсы на XML, такие как CSS, HTML и JavaScript. Для повышения производительности их следует минимизировать и сжать.
  • Вместо путей используйте стандартные формы SVG, такие как <rect>, <circle>, <ellipse>, <line> и <polygon>. Это уменьшит объём необходимой разметки и объём кода для парсинга и растеризации в браузере.
  • Если необходимо использовать пути, попробуйте уменьшить их. Упростите и объедините кривые и пути, где возможно. Инструмент simplify в Illustrator хорошо удаляет лишние точки даже в сложных работах, сглаживая неровности.
  • Избегайте групп. Если не можете, попробуйте упростить их.
  • Удалите невидимые слои.
  • Избегайте эффектов Photoshop и Illustrator. Они могут сконвертироваться в большие растровые изображения.
  • Внимательно проверьте наличие встроенных растровых изображений, которые не подходят для SVG.
  • Используйте инструмент для оптимизации SVG, здесь незаменим веб-интерфейс SVGOMG для SVGO. Если используете Sketch, то отличный плагин Sketch для SVGO уменьшает размер файла при экспорте.


Эффективность SVGO в режиме высокой точности (−29% от размера оригинального файла) и низкой точности (−38%)

SVGO — инструмент оптимизации SVG на Node. Он уменьшает размер файла, понижая точность чисел в definitions. Каждая цифра после точки — лишний байт, поэтому изменение точности (количества цифр) сильно влияет на размер файла. Но будьте очень осторожны, потому что снижение точности может визуально повлиять на формы изображения.


Важно отметить: хотя SVGO преуспел в предыдущем примере без чрезмерного упрощения путей и форм, часто случается иначе. Посмотрите, как с понижением точности искажается блик на ракете

SVGO из командной строки:


SVGO можно установить как CLI, если вы предпочитаете командную строку:

npm i -g svgo

Оптимизация SVG-файла:

svgo input.svg -o output.svg

Поддерживаются все возможные параметры, включая настройку точности с плавающей точкой:

svgo input.svg --precision=1 -o output.svg

См. readme для полного списка поддерживаемых параметров.

Не забудьте сжать SVG!




Кроме того, не забудьте зазиповать файлы SVG или выдавать их по протоколу Brotli. Текстовый формат будет очень хорошо сжиматься (~50% от исходника).

Когда Google выпустила новый логотип, мы объявили, что его минимальная версия занимает всего 305 байт.



Есть много продвинутых трюков, чтобы ещё сильнее ужать файл (вплоть до 146 байт)!

SVG-спрайты


SVG отлично подходит для иконок, предлагая визуализацию в виде спрайта без изворотливых обходных путей, необходимых для шрифтов. У него лучший контроль стилей CSS, чем в шрифтах (свойства SVG stroke), лучший контроль позиционирования (нет необходимости заморачиваться с псевдоэлементами и display) и SVG гораздо лучше поддерживается в браузерах.

Инструменты вроде svg-sprite и IcoMoon автоматизируют объединение SVG в спрайты, которые можно использовать в CSS Sprite, Symbol Sprite или Stacked Sprite. Стоит изучить практичные советы от Уны Кравец, как использовать gulp-svg-sprite в рабочем процессе. Сара Судеин в своём блоге описывает переход от шрифтов для иконок к SVG.

Дополнительные материалы


Советы Сары Соуэйдан по оптимизации выдачи SVG и «Практическая книга по SVG» Криса Койера превосходны. Я нашёл очень полезными статьи Андреаса Ларсена об оптимизации SVG (часть 1, часть 2). Могу также порекомендовать статью «Подготовка и экспорт значков SVG в Sketch».

Избегайте пережатия графики с потерей качества


Сжимать изображение всегда рекомендуется из исходника. Повторное пережатие чревато неприятными последствиями. Предположим, вы берете JPEG, который уже сжат с качеством 60. Если повторно сжать его с потерями, он будет выглядеть хуже. Каждый дополнительный раунд сжатия приведёт к дополнительной потере качества — информация удаляется, а артефакты накапливаются. Даже если вы пережимаете с установками высокого качества.

Чтобы избежать этой ловушки, сразу установите минимально приемлемое качество, и получите максимальную экономию с самого начала. Затем вы не пойдёте на повторное пережатие, потому что любое сжатие файла с потерями будет выглядеть плохо, хотя и уменьшит размер файла.


Пример из отличного видео и сопроводительной статьи Джона Снейерса показывает влияние пережатия в разных форматах. С такой проблемой можно столкнуться, если сохранять (уже сжатые) картинки из социальных сетей и повторно загружать их (с повторным сжатием). Потеря качества нарастает

MozJPEG (возможно, случайно) более устойчив к такой деградации благодаря треллис-квантованию. Вместо сжатия всех значений DCT как есть он ищет близкие значения в диапазоне +1/-1, чтобы сжать их в меньшем количестве бит. FLIF с потерей качества использует хак, похожий на PNG с потерей качества, где перед (повторным) сжатием кодек анализирует данные и решает, что выбросить.

Исходные файлы храните их в формате без потерь, например, PNG или TIFF, чтобы сохранить максимальное качество. Затем инструменты сборки или компрессоры подготовят сжатую версию, которую вы отдадите пользователям с минимальными потерями в качестве.

Сокращение ненужных расходов на декодирование и изменение размера


Все мы отдавали пользователям большие изображения со слишком высоким разрешением. За это приходится платить. Декодирование и изменение размера — ресурсоёмкие операции для браузера на обычном мобильнике. Если отдавать большие изображения, масштабируя их средствами CSS или атрибутами ширины/высоты, то вы увидите, как это повлияет на производительность.


Когда браузер получает изображение, он должен декодировать его из исходного исходного формата (например, JPEG) в растровое изображение в памяти. Часто изображение требует изменения размера (например, ширина установлена в процентах). Декодирование и изменение размера изображений — ресурсоёмкие операции, которые замедляют рендеринг

В идеале следует отдавать изображения, которые браузер отобразит без изменения размера. Так что отдавайте картинки минимального размера для соответствующих экранов и разрешений, используя srcset/sizes — в ближайшее время мы рассмотрим srcset.

Пропуск атрибутов width или height тоже может негативно повлиять на производительность. Без них браузер присваивает изображению наименьшую область-заполнитель, пока не получит достаточное количество байт для определения правильных размеров. В этот момент разметку документа приходится обновлять с помощью ресурсоёмкой операции reflow.


Браузерам нужно совершить несколько шагов, чтобы отрисовать картинку на экране. Получив изображение, его необходимо декодировать и зачастую изменить размер. Эти события можно отследить на временной шкале Chrome DevTools

Большие изображения также занимают память: примерно по 4 байта на пиксель после декодирования. Если вы не слишком аккуратны, то можете буквально повесить браузер; на низкобюджетных устройствах не так уж сложно довести ситуацию до свопа. Таким образом, следите за издержками на декодирование, изменение размера и потребление памяти.


Декодирование изображений может оказаться невероятно ресурсоёмким на мобильных телефонах среднего и нижнего уровня. В некоторых случаях оно в 5 и более раз медленнее, чем на десктопе

При разработке новой мобильной версии Twitter сильно повысил скорость декодирования изображений, установив правильные размеры. Для многих изображений время декодирования снизилось с от ~400 мс до ~19 мс!


Панель Timeline/Performance в Chrome DevTools показывает время декодирования изображения в Twitter Lite до и после оптимизации

Доставка изображений HiDPI с помощью srcset


Пользователи могут заходить на сайт через разные мобильные и десктопные устройства с экранами высокого разрешения. Соотношение пикселей устройства (DPR) (также называемое «соотношение пикселей CSS») определяет, как CSS должен интерпретировать разрешение экрана. Стандарт DPR создан производителями телефонов, чтобы увеличить разрешение и резкость мобильных экранов, не уменьшая элементы.

Для максимального качества следует отдавать изображения с наиболее подходящим разрешением. На устройства с экранами высокого разрешения отдаются изображения высокой чёткости (с DPR 2×, 3×), а на стандартные экраны — обычные изображения, так как картинки с DPR 2× и 3× значительно тяжелее.


Соотношение пикселей устройства: многие сайты отслеживают DPR популярных устройств через material.io и mydevice.io

srcset позволяет браузеру выбрать оптимальное изображение для каждого устройства. Например, взять картинку 2× для мобильного дисплея с DPR 2×. Браузеры без поддержки srcset могут взять дефолтный src, указанный в теге <img>.

<img srcset="paul-irish-320w.jpg,
             paul-irish-640w.jpg 2x,
             paul-irish-960w.jpg 3x"
     src="paul-irish-960w.jpg" alt="Paul Irish cameo">

CDN для изображений вроде Cloudinary и Imgix поддерживают DPR для выдачи картинки с оптимальным разрешением из одного источника.

Примечание: узнать больше о соотношении пикселей устройства и отзывчивых изображениях можно в этом бесплатном курсе Udacity и руководстве по изображениям на Web Fundamentals.

Напоминаю, что Client Hints — тоже подходящая альтернатива указанию всех возможных DPR и форматов в отзывчивой разметке. Вместо этого соответствующая информация добавляется к HTTP-запросу, чтобы веб-сервер выбрал наиболее подходящий вариант для конкретного экрана.

Художественное преобразование


Хотя выбор правильного разрешения важен, некоторые сайты думают ещё о красоте. Если у пользователя маленький экран, можно обрезать или увеличить масштаб — и отобразить объект иначе, наилучшим образом используя доступное пространство. Хотя художественное преобразование (art direction) выходит за рамки этой статьи, некоторые сервисы вроде Cloudinary предоставляют API-интерфейсы для автоматизации таких задач.


Эрик Портис показал отличный пример, как творчески использовать отзывчивые изображения. В этом примере характеристики основного объекта на иллюстрации изменяются, чтобы наилучшим образом использовать доступное пространство

Управление цветом


Цвет можно рассматривать минимум с трёх перспектив: биология, физика и печать. В биологии цвет — феномен восприятия. Объекты отражают свет в различных комбинациях длин волн. Световые рецепторы в глазах переводят эти волны в ощущение цвета. В физике важны частоты волн и энергия (яркость). Печать — это больше о цветовом охвате, красках и художественных моделях.

В идеале, все экраны и веб-браузеры в мире должны в точности одинаково отображать цвет. К сожалению, это не так. Управление цветом позволяет достичь компромисса в отображении цветов с помощью цветовых моделей, пространств и профилей.

Цветовые модели


Цветовые модели — это система для создания полного спектра из меньшего набора основных цветов. Есть различные типы цветовых пространств с разными параметрами для управления цветами. В некоторых пространствах меньше управляющих параметров, чем в других — например, для всех оттенков серого достаточно одного параметра яркости между чёрным и белым.

Два распространённых типа цветовых моделей — аддитивные и субтрактивные. Аддитивные цветовые модели типа RGB отображают цвет свечением, а субтрактивные типа CMYK — отражением (вычитанием).


В RGB красный, зелёный и синий свет добавляются в различных сочетаниях для получения широкого спектра цветов. CMYK (циан, маджента, жёлтый и чёрный) работает чернилами разного цвета, отнимая часть белого спектра бумаги

Статья «Понятие цветовых моделей и систем цвета» хорошо описывает другие цветовые модели и режимы, такие как HSL, HSV и LAB.

Цветовые пространства


Цветовые пространства — это определённый диапазон цветов, которые можно отобразить для данного изображения. Например, в изображении до 16,7 миллиона цветов, а различные цветовые пространства позволяют сузить или расширить этот диапазон. Некоторые разработчики считают, что цветовые модели и цветовые пространства — это одно и то же.

sRGB разработан на основе RGB как стандарт для интернета. Это небольшое цветовое пространство, которое обычно считают наименьшим общим знаменателем и самым безопасным вариантом для управления цветом в браузерах. Другие цветовые пространства (например, Adobe RGB или ProPhoto RGB, используемые в Photoshop и Lightroom) содержат более разнообразные цвета, но поскольку sRGB распространён в браузерах, играх и мониторах, обычно используют именно его.


Визуализация гаммы — диапазона цветов в цветовом пространстве

В цветовых пространствах используется три канала (красный, зелёный и синий), в каждом по 255 цветов в 8-битном режиме, что даёт 16,7 миллиона цветов. 16-битные картинки спосбоны отображать триллионы цветов.


Сравнение sRGB, Adobe RGB и ProPhoto RGB на изображении с Yardstick. Невероятно трудно проиллюстрировать эту концепцию, если ваш экран показывает только цвета sRGB. При сравнении обычной фотографии в sRGB и широкой гамме всё будет одинаково, кроме самых насыщенных «сочных» цветов

Цветовые пространства отличаются своей гаммой (диапазон цветов, которые они могут воспроизводить с оттенками), спектром и гамма-кривой. sRGB примерно на 20% меньше, чем Adobe RGB, ProPhoto RGB примерно на 50% шире, чем Adobe RGB. Фотографии выше взяты с Clipping Path.

Широкая гамма (wide-gamut) — это термин, означающий цветовые пространства шире sRGB. Такие типы дисплеев становятся всё более распространёнными. Тем не менее, многие цифровые дисплеи по-прежнему просто не способны отображать цветовые профили, которые значительно лучше sRGB. При сохранении для веба в Photoshop используйте опцию преобразования в sRGB, если только не рассчитываете на дисплеи с широкой цветовой гаммой.

Примечание: При работе с оригинальными фотографиями не используйте sRGB в качестве основного цветового пространства. Оно меньше, цветовых пространств в большинство камер и может привести к потере информации. Вместо этого работайте с широким цветовым пространством (например, ProPhoto RGB), в конвертируйте в sRGB только при экспорте для интернета.

Есть ли случаи, когда широкая гамма имеет смысл для веб-контента?


Да. Если изображение содержит очень насыщенный/сочный/яркий цвет — и вы хотите отобразить его на совместимых экранах. Впрочем, на реальных фотографиях такое редко случается. Зачастую можно легко подкрутить настройки, чтобы цвет выглядел ярким, не выходя за рамки гаммы sRGB.

Причина в том, что человеческое восприятие цвета не абсолютно. Восприятие работает относительно окружения — и его легко обмануть. Но если на картинке след флуоресцентного маркера, то конечно, легче его показать в широкой гамме.

Гамма-коррекция и сжатие


Гамма-коррекция (или просто гамма) управляет общей яркостью изображения. Изменение гаммы также может изменить соотношение красного и зелёного цветов. Изображения без гамма-коррекции часто выглядят блеклыми или тёмными.

В видео и компьютерной графике гамма используется для сжатия, аналогично сжатию данных. Это позволяет сжать полезные уровни яркости в меньшем количестве бит (8, а не 12 или 16). Человеческое восприятие яркости нелинейно пропорционально физическому количеству света. Представление цветов в их истинной физической форме было бы расточительным при кодировании для человеческого глаза. Гамма-сжатие (gamma compression) используется для кодирования яркости в масштабе, более близком человеческому восприятию.

С гамма-сжатием полезная шкала яркости умещается в 8 бит точности (0−255 в большинством цветов RGB), потому что единицы яркости кодируются нелинейно. Представьте, что вы находитесь в тёмной комнате с одной свечой. Зажгите вторую — и заметите значительное увеличение яркости. Добавьте третью свечу, и комната станет ещё ярче. А теперь представьте себя в комнате с сотней свечей. Зажгите 101-ю, 102-ю свечи — и вы не заметите никаких изменений.

В обоих случаях физически добавили одинакового количество света. Но поскольку глаза менее чувствительны к яркому свету, гамма-компрессия «сжимает» яркие значения, поэтому в физических единицах там кодируется меньшая точность, но сам масштаб скорректирован для людей — и с человеческой точки зрения все значения одинаково точны.

Примечание: Гамма-коррекция или сжатие здесь отличаются от гамма-кривых в «Фотошопе», правильное гамма-сжатие ни на что не похоже.

Цветовые профили


Цветовой профиль — это информация, описывающая цветовое пространство устройства. Он используется для преобразования между различными цветовыми пространствами. Задача профилей — чтобы изображения были максимально похожи на всех типах экранов и носителей.

Изображения могут иметь встроенный цветовой профиль по стандарту Международного цветового консорциума (ICC), чтобы точно определить цвета. Профили поддерживаются в разных форматах, включая JPEG, PNG, SVG и WebP, и большинство основных браузеров тоже поддерживают встроенные профили ICC. Если картинка открывается в программе и известен профиль монитора, то цвета корректируются соответствующим образом.

Примечание: Цветовые профили некоторых мониторов аналогичны sRGB, так что они не смогут отобразить цвета из более широкой гаммы. Поэтому внедрение цифровых профилей в изображения может быть ограничено. Учитывайте особенности своей целевой аудитории.

Встроенные цветовые профили также значительно увеличивают размер изображений (иногда на 100 КБ и больше), поэтому будьте осторожны. Инструменты вроде ImageOptim автоматически удаляют все цветовые профили, какие найдут. Если профиль ICC удалён, браузер начнёт отображать картинку в цветовом пространстве вашего монитора, что может привести к изменению насыщенности и контраста. Так что есть смысл поискать компромисс для каждого конкретного случая.

На сайте Nine Degrees Below отличная подборка ресурсов по управлению цветовыми профилями ICC, если вам нужна дополнительная информация.

Цветовые профили и браузеры


В прежних версиях Chrome не было особой поддержки управления цветом, но ситуацию исправили в 2017 году, внедрив функцию Color Correct Rendering. Если профиль дисплея отличается от sRGB (последние MacBook Pro), то он преобразуют цвета из sRGB в профиль дисплея. Это означает, что цвета станут более похожими в разных системах и браузерах. Браузеры Safari, Edge и Firefox тоже учитывают профили ICC, поэтому изображения с разными профилями теперь отображаются корректно, независимо от того, у вас дисплей с широкой цветовой гаммой или нет.

Примечание: Отличное руководство о разнообразных способах использования цвета в вебе — «Справочник нерда по цвету в интернете» Сары Дразнер.

Спрайты


У спрайтов изображений (или CSS-спрайтов) долгая история, они поддерживаются всеми браузерами и были популярным способом уменьшить количество загружаемых картинок путём объединения их в одно более крупное изображение, которое нарезается на части.


Спрайты изображений по-прежнему широко используются на крупных сайтах в продакшне, включая главную страницу Google

По стандарту HTTP/1.x некоторые применяли спрайты для уменьшения количества HTTP-запросов. Это имело ряд преимуществ, но требовало аккуратности из-за проблемы с инвалидацией кэша — изменения любой небольшой части спрайта приведут к инвалидации всего изображения в кэше.

Сейчас разбиение на спрайты противоречит рекомендациям HTTP/2. Поскольку стало возможно отправлять много запросов в одном соединении, то лучше загружать картинки по отдельности. Оцените варианты для своей ситуации.

Ленивая загрузка некритических изображений


Ленивая (отложенная) загрузка — это практика повышения производительности, когда загрузка изображений в браузер задерживается до тех пор, пока реально не понадобится пользователю. Например, картинки загружаются асинхронно при прокрутке страницы. Это может экономить трафик дополнительно к сжатию изображений.



Попадающие на экран картинки загружаются сразу. Но остальные в этот момент ещё не видны. Их следует загружать не сразу, а позже — это и есть ленивая загрузка. Она происходит только если и когда пользователь прокручивает страницу вниз.

Ленивая загрузка пока не поддерживается самими браузерами (хотя в прошлом такое обсуждалось). Вместо этого используется JavaScript.

Почему полезна отложенная загрузка?


У неё много преимуществ:

  • Экономия трафика. Вы загружаете минимальное количество ресурсов. Это всегда хорошо, особенно на смартфонах с тарифами на трафик.
  • Экономия заряда батареи. Меньше нагрузки на браузер — меньше расход батареи.
  • Увеличение скорость загрузки. Сокращение времени загрузки тяжёлого сайта с обилием графики с нескольких секунд почти до нуля дорогого стоит. Фактически, эта разница может сохранить посетителя на сайте, а не добавить единичку в статистику отказов.

Впрочем, как и с другими инструментами, с большой силой приходит большая ответственность.

Избегайте отложенной загрузки изображений в области видимости. Используйте её для длинных списков (например, продуктов или пользовательских аватар). Не применяйте её для главной картинки на странице. Ленивая загрузка в области видимости может замедлить загрузку как технически, так и для человеческого восприятия. Она убивает предзагрузку и прогрессивную загрузку, а JavaScript генерирует лишнюю работу для браузера.

Будьте очень осторожны с ленивой загрузкой изображений при прокрутке. Если ждать непосредственно события прокрутки, то пользователь может увидеть заполнители вместо картинок или получить картинки до скроллинга на них. Одна из рекомендаций — начинать ленивую загрузку следующих изображений сразу после того, как на экране отобразилось предыдущее, независимо от взаимодействия с пользователем.

Кто использует отложенную загрузку?


Ленивую загрузку применяет большинство крупных сайтов с большим количеством изображений. Например, Medium и Pinterest.


Пример превью с гауссовым размытием иллюстраций на Medium

На некоторых сайтах (например, Medium) для предварительного просмотра отображается небольшая размытая картинка (около 100 байт), которое после отложенной загрузки превращается в иллюстрацию нормального качества.

Хосе М. Перес рассказал, как реализовать эффект Medium с помощью CSS-фильтров. Он экспериментировал с разными графическими форматами. Facebook тоже описывал свой знаменитый подход с 200-байтовыми заполнителями для заглавных фотографий. Если вы пользуетесь Webpack, то LQIP loader поможет автоматизировать некоторые из этих процедур.

Чтобы увидеть ленивую загрузку, достаточно открыть любимый каталог качественных фотографий, а затем прокрутить страницу вниз. Почти всегда вы увидите, что сайт загружает только несколько картинок с полным разрешением, а остальное — заполнители. По мере прокрутки заполнители заменяются изображениями в полном разрешении. Это ленивая загрузка.

В последнее время получила распространение новая техника векторных, а не растровых заполнителей. Её предложил Тобиас Балдауф в своём инструменте SQIP. Там утилита Primitive генерирует SVG-превью из нескольких простых форм, примерные совпадающих с основными чертами изображения. Затем SVG оптимизируется с помощью SVGO — и накладывается фильтр гауссова размытия. В результате получается заполнитель SVG размером всего 800−1000 байт, который выглядит чётким на любых экранах и даёт осмысленное представление, что находится на реальной картинке. Очевидно, можно комбинировать ленивую загрузку и предварительный просмотр изображений в низком качестве.

Как применить отложенную загрузку?


Для отложенной загрузки есть ряд методов и плагинов. Я рекомендую lazysizes Александра Фаркаса из-за его достойной производительности, функциональности, дополнительной интеграции с Intersection Observer и поддержки плагинов.

Что умеет Lazysizes?


Lazysizes — это библиотека JavaScript, она не требует настройки. Просто скачайте минифицированный файл js и включите его в веб-страницу.

Ниже пример кода из файла README:

Добавьте класс 'lazyload’ к изображениям/фреймам в сочетании с атрибутом data-src и/или data-srcset.

Дополнительно можно добавить атрибут src с изображением низкого качества:

<!-- non-responsive: -->
<img data-src="image.jpg" class="lazyload" />

<!-- responsive example with automatic sizes calculation: -->
<img
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w" class="lazyload" />

<!-- iframe example -->

<iframe frameborder="0"
    class="lazyload"
    allowfullscreen=""
    data-src="//www.youtube.com/embed/ZfV-aYdU4uE">
</iframe>

Для веб-версии этой книги я связал Lazysizes с Cloudinary (хотя вы можете использовать любую альтернативу). Это позволяет свободно и с минимальными усилиями экспериментировать с различными масштабами, качеством, форматами и независимо от того, нужна ли прогрессивная загрузка:



Особенности Lazysizes:


  • Автоматически определяет изменения в видимости текущих и будущих элементов ленивой загрузки
  • Поддержка стандартных отзывчивых изображений (picture и srcset)
  • Автоматический расчет размеров и алиасы для медиазапросов
  • Работает с сотнями изображений/фреймов на CSS, в насыщенных скриптами страницах и веб-приложениях
  • Расширяемость: поддерживает плагины
  • Лёгкое, но зрелое решение
  • Улучшение SEO: не скрывает изображения/активы от краулеров

Другие способы ленивой загрузки


Lazysizes — не единственный вариант. Есть и другие библиотеки:


В чём недостатки ленивой загрузки?


  • Программы чтения с экрана, некоторые поисковые боты и пользователи с отключенным JavaScript не увидят изображения, загруженные с помощью JavaScript. Но этого недостатка можно избежать запасным вариантом <noscript>.
  • Прослушивание событий прокрутки может негативно повлиять на производительность скроллинга. Браузер попытается многократно перерисовывать экран (redraw), но грамотные библиотеки отложенной загрузки смогут смягчить этот негативный эффект за счёт дросселирования. Одно из возможных решений — Intersection Observer, который поддерживается в библиотеке lazysizes.

Отложенная загрузка — распространённый способ экономии трафика, снижения затрат и улучшения взаимодействия с пользователем. Оцените, насколько она полезна в вашем случае. Для дополнительной информации см. статьи «Ленивая загрузка изображений» и «Реализация прогрессивной загрузки в Medium».

Как избежать ловушки display:none


Старые решения для отзывчивых изображений ошибочно обрабатывали запросы изображений при установке свойства CSS display. Это могло привести к значительному увеличению количества запросов, что является ещё одной причиной, почему предпочтительно использовать <picture> и <img srcset>.

Вы когда-нибудь писали запрос media, который в определённых условиях прячет картинку в display:none?

<img src="img.jpg">
<style>
@media (max-width: 640px) {
    img {
        display: none;
    }
}
</style>

Или скрывает изображения с помощью класса display:none?

<style>
.hidden {
  display: none;
}
</style>
<img src="img.jpg">
<img src=“img-hidden.jpg" class="hidden">

Быстрая проверка в сетевой панели Chrome DevTools показывает, что такие «спрятанные» изображения всё равно загружаются. На самом деле это корректное поведение браузера согласно спецификации встроенных ресурсов.



Помогает ли display:none избежать запроса src?


<div style="display:none"><img src="img.jpg"></div>

Нет. Указанное изображение всё равно будет запрошено. Здесь библиотека не может полагаться на display:none, потому что запрос отправляется раньше, чем JavaScript изменит src.

Помогает ли display:none избежать запроса background: url()?


<div style="display:none">
  <div style="background: url(img.jpg)"></div>
</div>

Утвердительный ответ. Фон CSS не извлекается при разборе элемента. Расчёт стилей CSS для дочерних элементов с display:none менее полезен, так как они не влияют на рендеринг документа. Фоновые изображения дочерних элементов не рассчитываются и не загружаются.

У Джейка Арчибальда есть отличный квест-викторина по ловушкам display:none. Если сомневаетесь, как конкретный браузер обрабатывает запросы изображений, откройте DevTools и проверьте сами.

Опять же, где возможно используйте <picture> и <img srcset> вместо того, чтобы полагаться на <display:none>.

Есть ли смысл пользоваться CDN для обработки изображений?


Время, потраченное на чтение статей для настройки своего конвейера обработки изображений и его последующей доработки зачастую намного дороже, чем плата за эту услугу. Cloudinary предлагает бесплатный сервис, Imgix даёт бесплатную пробную версию, есть свободная альтернатива Thumbor, так что вариантов немало.

Для самой быстрой загрузки страницы нужно оптимизировать загрузку изображений, включая выдачу отзывчивых изображений со сжатием на стороне сервера, автоматический выбор оптимального формата и изменение размера. Важно отдавать изображение правильного размера на правильное устройство в правильном разрешении — и как можно быстрее. Сделать это не так просто, как кажется.

Свой сервер или CDN?


Манипуляции с изображениями — специфическая тема. Тут всё постоянно меняется, поэтому начнём с цитаты опытного специалиста, а затем продолжим.

«Если ваш продукт сам по себе не связан с обработкой изображений, то не делайте это самостоятельно. Сервисы вроде Cloudinary [или Imgix, прим. авт.] справятся намного лучше и эффективнее. И если вы беспокоитесь о цене, подумайте, во сколько обойдутся разработка и обслуживание, а также хостинг, хранение и доставка» — Крис Гмыр

На данный момент мы склонны согласиться, что лучше использовать CDN для обработки изображений. Рассмотрим два таких сервиса — как они соответствуют списку упомянутых задач.

Cloudinary и Imgix


Cloudinary и Imgix — хорошо известные CDN для обработки изображений. Их используют сотни тысяч разработчиков и компаний по всему миру, включая Netflix и Red Bull.

Основное


Первое огромное преимущество CDN перед собственным решением — то, что они используют распределённую глобальную сетевую систему, чтобы хранить ваши изображения ближе к вашим пользователям. И с CDN вам гораздо проще гарантировать актуальность сервиса с будущими изменениями технологий, поскольку не каждый сможет самостоятельно отслеживать тенденции, вносить изменения — это требует обслуживания, отслеживания поддержки браузерами новых форматов и погружения в жизнь сообщества, которое занимается сжатием изображений.

Второе: у каждого сервиса многоуровневую тарифный план: У Cloudinary бесплатный тариф, у Imgix недорогой стартовый план. Imgix предлагает бесплатную пробную версию, это почти то же самое, что и бесплатный тариф.

Третье: у обоих сервисов есть API. Разработчики могут программно подключаться к CDN и автоматизировать процесс. Доступны клиентские библиотеки, плагины для фреймворков и документация по API, хотя некоторые опции доступны только на дорогих тарифах.

Перейдём к обработке изображений


Ограничим дискуссию статичными изображениями. Cloudinary и Imgix предлагают широкий спектр методов обработки изображений. В стандартных и бесплатных тарифах оба поддерживают базовые функции: сжатие, изменение размера, обрезка, генерация уменьшенных копий.


Cloudinary Media Library: По умолчанию Cloudinary выдаёт обычные, а не прогрессивные JPEG. Чтобы активировать эту опцию, поставьте соответствующий значок в «Дополнительных параметрах» или используйте флаг fl_progressive

Cloudinary называет семь широких категорий преобразования, в общей сложности 48 подкатегорий. У Imgix более 100 операций обработки изображений.

Что происходит по умолчанию?


Cloudinary по умолчанию выполняет следующие оптимизации:

  • Кодирование в JPEG с помощью MozJPEG (выбрали вместо Guetzli по умолчанию).
  • Очистка от метаданных (исходное изображение остаётся нетронутым). Чтобы изменить это поведение и отдавать картинки с метаданными, добавьте флаг keep_iptc.
  • Возможность генерации WebP, GIF, JPEG и JPEG-XR с автоматическим качеством. Чтобы изменить настройки по умолчанию, задайте параметр качества вручную.
  • Оптимизация размера файлов с минимальным влиянием на качество при генерации PNG, JPEG или GIF.

Imgix по умолчанию не запускает такие оптимизации, как Cloudinary, но позволяет установить дефолтное качество. В Imgix автоматические параметры помогают автоматизировать базовый уровень оптимизации в каталоге изображений.

В настоящее время используется четыре метода:

  • Сжатие
  • Визуальное улучшение
  • Преобразование форматов файлов
  • Удаление эффекта красных глаз

Imgix поддерживает следующие форматы изображений: JPEG, JPEG2000, PNG, GIF, анимированный GIF, TIFF, BMP, ICNS, ICO, PDF, PCT, PSD, AI.

Cloudinary поддерживает такие форматы: JPEG, JPEG 2000, JPEG XR, PNG, GIF, анимированный GIF, WebP, анимированный WebP, BMP, TIFF, ICO, PDF, EPS, PSD, SVG, AI, DjVu, FLIF, TARGA.

Что насчёт производительности?


Производительность CDN в основном зависит от задержки и скорости.

Задержка всегда немного больше для полностью некэшированных изображений. Но как только картинка попадает в кэш и расходится по серверам в сети, глобальный CDN находит самый близкий маршрут к пользователю. Вместе с экономией на размере файлов это почти всегда устраняет проблемы с задержкой по сравнению с неоптимизированными изображениями или одиночными серверами, которые пытаются обслужить всю планету.

У обоих CDN широкое покрытие и быстрые серверы, за счёт чего снижается задержка и увеличивается скорость загрузки. Скорость влияет на время загрузки страницы, а это одна из самых важных метрик для пользователей и конверсии.

Что же лучше?


У Cloudinary около 160 000 клиентов, включая Netflix, eBay и Dropbox. Imgix не сообщает количество пользователей, но оно меньше, чем у Cloudinary. Тем не менее, база Imgix включает в себя таких тяжеловесов как Kickstarter, Exposure, unsplash и Eventbrite.

В обработке изображений столько параметров не поддаются объективной оценке, что затруднительно сравнить производительность двух служб. Многое зависит от того, как вы хотите обработать изображение (это займёт разное время), какой размер и разрешение нужны в итоге. В конце концов, самым важным фактором для вас может оказаться стоимость.

CDN стоят денег. Тяжёлый сайт с большим трафиком может платить сотни долларов в месяц на CDN. Необходим определённый уровень знаний и навыков программирования, чтобы получить максимальную отдачу от этих услуг. Но если вы не делаете ничего необычного, то особых проблем не возникнет.

Вывод


Если вы сейчас отдаёте изображения с собственного сервера или планируете так поступить, возможно, вам следует подумать о CDN.

Кэширование изображений


Ресурсы могут задавать правила кэширования через HTTP-заголовки кэша. В частности, Cache-Control определяет, кто и как долго должен кэшировать ответы.

Большинство изображений — статические ресурсы, которые не изменятся в будущем. Наилучшая стратегия для них — агрессивное кэширование.

При настройке HTTP-заголовков кэширования, установите Cache-Control со сроком max-age на год (например, Cache-Control:public; max-age=31536000). Такое агрессивное кэширование хорошо работает для большинства изображений, особенно для долгоживущих, таких как аватары и картинки в заголовках страниц.

Примечание: если вы отдаёте изображения с помощью PHP, то кэширование отключится из-за дефолтной настройки session_cache_limiter. Проблему можно обойти с помощью session_cache_limiter('public'), указав public и max-age=. Как вариант, отключение опции и настройка кастомных заголовков управления кэшем.

Предварительная загрузка важных ресурсов


Критические ресурсы можно предварительно загрузить с помощью <link rel=preload>.

<link rel=preload> — это декларативная загрузка, которая заставляет браузер отправить запрос на ресурс, не блокируя событие onload для документа. Это повышает приоритет запросов на ресурсы, которые в противном случае будут обнаружены только позже во время парсинга.

Для предварительной загрузки изображений значение as указывается как image:

<link rel="preload" as="image" href="logo.jpg"/>

Таким способом оптимизируется загрузка ресурсов для <img>, <picture>, srcset и SVG.

Примечание: <link rel=preload> поддерживается в Chrome и браузерах на движке Blink, таких как Opera и Safari Tech Preview, а также реализована в Firefox.

Такие сайты, как Philips, Flipkart и Xerox, используют <link rel=preload> для предварительной загрузки своих логотипов (часто используемых в начале документа). Kayak тоже применяет предварительную загрузку, чтобы главная картинка в заголовке загружалось максимально быстро.



Что такое заголовок Link preload?


Предзагрузка ссылки задаётся тегом HTML или в заголовке HTTP Link Header. В любом случае ссылка указывает браузеру начать загрузку ресурса в кэш памяти, потому что страница с высокой степенью вероятности ожидает этот ресурс и нельзя ждать, пока сканер предварительной загрузки или синтаксический анализатор его обнаружит.

Заголовок для изображений будет выглядеть следующим образом:

Link: <https://example.com/logo-hires.jpg>; rel=preload; as=image

Когда Financial Times представила такой заголовок на своём сайте, пользователи стали открывать контент на 1 секунду быстрее:


Снизу: с <link rel=preload>, сверху: без. Сравнение для Moto G4 на канале 3G по тесту WebPageTest до и после оптимизации

Аналогичным образом и Википедия ускорила загрузку «до логотипа», как описывается в их исследовании.

Какие подводные камни в этой оптимизации?


Нужно быть уверенным, что предварительная загрузка именно этого ресурса абсолютно необходима, потому что он сдвигает остальной контент в конец очереди. Может быть следует сосредоточить усилия на другом контенте?

Важно избегать rel=preload для предварительной загрузки изображений без широкой поддержки в браузерах (например, WebP) и избегать применения в отзывчивых изображениях, определённых в srcset, где источник картинки зависит от типа устройства.

Для дополнительной информации ознакомьтесь со статьями «Предзагрузка и приоритеты в Chrome» и «Предварительная загрузка: для чего она хорошо подходит?»

Бюджеты веб-производительности для изображений


Бюджет производительности — это максимальный лимит, который разработчики стараются не превышать. Например, «не больше 200 КБ картинок на одной странице» или «пользовательский интерфейс должен загружаться быстрее, чем за 3 секунды». Когда бюджет не выполняется — изучите, почему это происходит и как исправить ситуацию.

Бюджеты помогают обсуждать результаты работы. Когда дизайн или бизнес-решение влияет на производительность, сверяйтесь с бюджетом. Если изменение не вписывается в бюджет, это основание для того, чтобы отложить или пересмотреть его.

Я обнаружил, что бюджет производительности выполняется лучше всего, если мониторинг автоматизирован. Вместо изучения сетевых графиков вручную запускается сервис, который автоматически сигнализирует о превышении бюджета. Два таких полезных сервиса — Calibre и SpeedCurve.

Как только определён бюджет по размеру изображений, SpeedCurve начинает мониторинг и предупреждает о превышении:



Calibre предлагает установку бюджета для каждого класса устройств. Это полезно, поскольку бюджет по размеру картинок для десктопного ПК по WiFi может сильно отличаться от бюджета для мобильников.



Заключительные рекомендации


В конечном счёте выбор стратегии оптимизации изображений сводится к типам изображений, которые вы отдаёте пользователям, и разумному набору критериев оценки на выбор. Это может быть SSIM или Butteraugli, а на маленьком наборе иллюстраций можно довериться собственному глазу: что выглядит лучше, а что хуже.

Вот мои заключительные рекомендации:


Если вы не можете отдавать изображения в разных форматах, в зависимости от поддержки в браузере:

  • Guetzli + jpegtran из MozJPEG хорошо оптимизируют при качестве JPEG более 90.
    • Для веба качество q=90 слишком расточительно. Для обычных картинок достаточно q=80, а для DPR 2× даже q=50. Поскольку Guetzli не выходит на такой низкий уровень, то для веба можно использовать MozJPEG.
    • Корнель Лесински недавно улучшил команду cjpeg в mozjpeg, добавив крошечный профиль sRGB, чтобы помочь Chrome отображать естественный цвет на дисплеях с широкой цветовой гаммой.
  • PNG pngquant + advpng обеспечивает довольно хорошее соотношение скорости/сжатия.

Если вы можете отдавать изображения в разных форматах, в зависимости от поддержки в браузере, используя <picture>, заголовок Accept или Picturefill:

  • Отдавайте WebP для браузеров, которые его поддерживают
    • Создавайте WebP из оригинальных изображений 100% качества. Иначе вы будете отдавать в браузеры картинки худшего качества и большего объёма с искажениями JPEG и искажениями WebP! Если сжимаете исходные изображения кодеком WebP, то искажения будут менее заметны, а уровень сжатия выше.
    • Настройки по умолчанию WebP -m 4 -q 75 хороши для большинства случаев как оптимальное соотношение скорости и степени сжатия.
    • У WebP есть специальный режим сжатия без потерь (-m 6 -q 100), который уменьшает файлы, изучив все сочетания параметров. Это на порядок медленнее, но стоит того для статических ресурсов.
  • Запасной вариант — Guetzli/MozJPEG для браузеров, которые не поддерживают WebP.

Удачной компрессии!

Примечание: для более практических советов по оптимизации изображений настоятельно рекомендую книгу Web Performance in Action Джереми Вагнера. В книге High Performance Images тоже много отличных советов и нюансов.

Мелочи


  • JPEG XT определяет расширения спецификации JPEG 1992 года. Чтобы гарантировать идеальную совместимость со старым стандартом пришлось уточнить спецификацию 1992 года, а кодек libjpeg-turbo выбран в качестве эталонной реализации (как самый популярный).
  • PIK — это новый графический кодек, за которым стоит следить. Он совместим с JPEG, имеет более эффективное цветовое пространство и использует преимущества Guetzli. Он декодирует на 33% медленнее JPEG, но удаляет из файлов на 54% больше лишней информации, чем libjpeg. Он быстрее в Guetzli в декодировании. Исследование психовизуального сходства современных кодеков показало, что PIK намного превосходит альтернативы. К сожалению, кодек пока на ранних стадиях разработки, и кодирование пока неприемлемо медленно (сравнение проводилось в августе 2017 года).
  • Для оптимизации изображений часто рекомендуют ImageMagick. Это хороший инструмент, но результат его работы обычно нуждается в дополнительной оптимизации, а другие инструменты справляются лучше. Мы рекомендуем libvips, хотя это более низкоуровневый инструмент и более требователен к технической квалификации пользователя. У ImageMagick также периодически находили уязвимости в безопасности, о которых желательно знать.
  • Blink (движок рендеринга в Chrome) декодирует изображения вне основного потока. Перенос декодера в поток компоновщика освобождает основной поток для работы над другими задачами. Мы называем это отложенным декодированием. Но даже в этом случае работа декодера занимает критический путь для вывода фрейма на экран, поэтому он всё ещё может вызвать подтормаживание и рывки анимации. img.decode() API должен устранить эту проблему.
Tags:
Hubs:
+61
Comments31

Articles