- PVSM.RU - https://www.pvsm.ru -
Автор электронной книги — Эдди Османи, один из руководителей разработки Google Chrome
Оптимизацию графики обязательно надо автоматизировать. О ней легко забыть, рекомендации меняются, да и сам контент может легко проскользнуть мимо конвейера сборки. Для автоматизации при сборке используйте imagemin [1] или libvips [2]. Есть и много других.
Большинство CDN (например, Akamai [3]) и сторонних решений вроде Cloudinary [4], imgix [5], Fastly Image Optimizer [6], Instart Logic SmartVision [7] и ImageOptim API [8] предлагают комплексные автоматизированные решения для оптимизации изображений.
На чтение статей и настройку конфигурации вы потратите время, которое дороже оплаты их услуг (у Cloudinary есть бесплатный [9] тариф). Но если всё-таки не хотите отдавать работу на аутсорсинг по соображениям стоимости или из-за дополнительной latency, то выбирайте приведённые выше варианты с открытым исходным кодом. Проекты Imageflow [10] или Thumbor [11] предлагают альтернативу на собственном
Как минимум, используйте ImageOptim [13]. Он значительно уменьшает размер при сохранении визуального качества. Есть версии [14] под Windows и Linux.
Более тщательный подход: прогоняйте JPEG-файлы через MozJPEG [15] (для веб-контента приемлемо качество q=80
или ниже) и рассмотрите поддержку Progressive JPEG [16]. Файлы PNG пропускайте через pngquant [17], а SVG — через SVGO [18]. Явно укажите очистку от метаданных (--strip
для pngquant), чтобы избежать раздутия файлов. Вместо сумасшедших гигантских анимированных GIF отдавайте пользователям видео H.264 [19] (или WebM [20] для Chrome, Firefox и Opera)! Если не можете себе это позволить, то хотя бы используйте Giflossy [21]. Когда есть возможность потратить пару циклов CPU, а вам нужно изображение лучшего качества и вы готовы смириться с длительным временем кодирования, то попробуйте Guetzli [22].
Некоторые браузеры анонсируют поддержку графических форматов через заголовок Accept. Это можно использовать при выборе формата для выдачи: например, формат WebP [23] для браузеров на основе Blink, таких как Chrome, и вариант JPEG/PNG для других браузеров.
Сжатие всегда можно улучшить. Есть инструменты для генерации и выдачи srcset
. В браузерах на основе Blink выбор ресурсов автоматизируется с помощью client-hints [24] — и вы сэкономите трафик на пользователях, которые указали в браузере опцию «экономия данных» через подсказку Save-Data [25].
Чем меньше размер изображений, тем удобнее пользователям — особенно с мобильными телефонами. В этой статье мы рассмотрим способы сжатия графики современными методами с минимальным влиянием на качество.
Изображения составляют огромную долю интернет-трафика. Согласно HTTP Archive [65], 60% объёма веб-страниц — это графика в форматах JPEG, PNG и GIF. По состоянию на июль 2017 года изображения составляли 1,7 МБ на средней веб-странице объёмом 3,0 МБ.
Эксперимент Тэмми Эвертса доказал [66], что добавление изображений на страницу или увеличение существующих изображений повышает коэффициент конверсии (процент посетителей, которые становятся клиентами — прим. пер.). Так что картинки никуда не денутся — вот почему важно вложиться в эффективную стратегию по их сжатию.
Исследование Soasta/Google [67] от 2016 года показало, что иллюстрации — это второй предиктор конверсии, а у эффективных страниц на 38% меньше картинок
Оптимизация изображений включает ряд мер. Выбор зависит от того, какую потерю качества считать приемлемой.
Оптимизация: выбрать правильный формат, аккуратно сжать и установить приоритеты загрузки разных изображений
Типичная оптимизация включает сжатие, грамотную выдачу изображений на основе размера с помощью тегов <picture>/<img srcset>
и изменение размера.
Согласно HTTP Archive [68], на 95-м процентиле (в кумулятивной функции распределения) каждая картинка поддаётся уменьшению на 30 КБ!
У нас ещё очень много изображений, которые можно оптимизировать.
Бесплатная программа ImageOptim уменьшает размер графики с помощью современных методов сжатия и удаления ненужных метаданных EXIF
Если вы дизайнер, есть ещё плагин ImageOptim для Sketch [69], который оптимизирует ресурсы при экспорте. Я нашёл, что он экономит массу времени.
Проведите аудит сайта с помощью WebPageTest.org [70].
В разделе Compress Images отчёта WebPageTest перечислены картинки, которые можно сжать более эффективно, при этом оценивается потенциальный выигрыш по размеру файлов
Сервис Lighthouse [71] тоже осуществляет аудит производительности, в том числе проводит проверку оптимизации изображений. Он показывает картинки, которые можно сжать сильнее и которые можно поставить в ленивую загрузку.
Начиная с Chrome 60 этот сервис работает в панели аудита [72] Chrome DevTools:
Lighthouse проводит аудит с прицелом на производительность, лучшие практики или прогрессивные функции веб-приложений (на выбор)
Вам могут быть известны другие инструменты аудита, такие как PageSpeed Insights [73] и Website Speed Test [74] от Cloudinary, включающий подробный аудит изображений.
Как отметил Илья Григорик в своём превосходном руководстве по оптимизации изображений [75], «правильный формат» сочетает в себе желаемый визуальный результат и функциональные требования. У вас растровая или векторная графика?
Растровая графика [76] кодирует значения каждого пикселя на прямоугольной сетке пикселей. Они не зависят от разрешения или масштаба. С такой графикой хорошо справляются WebP или широко поддерживаемые форматы, такие как JPEG или PNG. Растровая графика используется там, где нужен фотореализм. Guetzli, MozJPEG и другие упомянутые инструменты подходят для растровой графики.
Векторная графика [77] применяет точки, прямые и полигоны для представления изображений с простыми геометрическими фигурами (например, логотипов). Она предлагает высокое разрешение и масштабирование. Для такого варианта лучше подходят форматы вроде SVG.
Выбор неправильного формата дорого вам обойдётся. Менять формат следует с осторожностью, проведя эксперименты с возможной экономией в разных форматах.
Джереми Вагнер в своей лекции осветил компромиссы [78], которые стоит учитывать при оценке разных форматов в процессе оптимизации.
Вероятно, JPEG [79] — самый популярный в мире формат графики. Как отмечалось ранее, 45% изображений [80] на сайтах в HTTP Archive — это картинки JPEG. Ваш телефон, цифровая камера, старая веб-камера — все они обычно поддерживают данный кодек. Он очень древний, используется аж с 1992 года. За это время проведено огромное количество исследований, как улучшить компрессию JPEG.
JPEG — алгоритм сжатия с потерями, который отбрасывает «лишнюю» информацию для экономии места. Задача состоит в максимальном сохранении визуальной точности с минимизацией размеров файлов.
Форматы вроде JPEG лучше всего подходят для фотографий или изображений с большим количеством цветов. Большинство инструментов оптимизации позволит выбрать приемлемый уровень сжатия: более сильное сжатие уменьшает размер файлов, но может привнести артефакты: гало или блочность.
Видимые артефакты сжатия JPEG нарастают по мере перехода от наилучшего качества к худшему. Заметьте, что показатели качества изображения в разных инструментах могут сильно отличаться
При выборе уровня сжатия следует учитывать, какое качество необходимо для изображений:
Далее поговорим о режимах сжатия JPEG, которые сильно влияют на результат.
Примечание: возможно, мы иногда переоцениваем качество изображения, которое нужно пользователям. Качество можно рассматривать как отклонение от идеального исходника. Это субъективный показатель.
В формате JPEG есть ряд различных режимов сжатия. Три популярных: базовый (последовательный), прогрессивный JPEG (PJPEG) и сжатие без потерь.
Базовый JPEG (режим по умолчанию в большинстве редакторов и оптимизаторов) кодирует и декодирует относительно просто: сверху вниз. Когда базовый JPEG загружается по медленному или нестабильному соединению, пользователь сначала увидит верхнюю часть картинки. Режим сжатия JPEG без потерь похож на базовый, только с меньшей степенью сжатия.
Базовый JPEG (baseline JPEG) загружается сверху вниз, а прогрессивный JPEG загружается от размытого до резкого
Прогрессивный JPEG делит изображение на ряд проходов. Первый проход показывает картинку в размытом виде и низком качестве, а последующие проходы постепенно улучшают качество. Каждый проход повышает уровень детализации. В конце концов создаётся полноценное изображение.
Базовый JPEG загружает изображение сверху вниз. PJPEG сначала показывает размытую картинку, а потом повышает разрешение. Пэт Минан разработал интерактивный инструмент [81] для тестирования и изучения прогрессивных файлов JPEG
Оптимизация JPEG без потерь достигается путём удаления EXIF-заголовков [82] от цифровых камер и редакторов, оптимизации таблиц Хаффмана [83] и повторного сканирования изображения. Такие инструменты, как jpegtran [84], обеспечивают сжатие без потерь, перестраивая сжатые данные без ухудшения качества изображения. jpegrescan [85], jpegoptim [86] и mozjpeg [15] (которые мы скоро рассмотрим) тоже поддерживают сжатие JPEG без потерь.
Способность PJPEG показывать превью при загрузке повышает производительность — пользователям кажется, что изображение загружается быстрее по сравнению со стандартной графикой.
На медленных 3G-соединениях это позволяет примерно увидеть картинку, когда получена только часть файла — и принять решение, дожидаться его полной загрузки или нет. Это может оказаться удобнее, чем загрузка изображения сверху вниз, как в базовом JPEG.
В 2015 году Facebook перешёл на PJPEG (для своего приложения iOS) [87] и трафик уменьшился на 10%. Они смогли показать изображение хорошего качества на 15% быстрее, чем раньше, оптимизировав воспринимаемое время загрузки, как показано на рисунке выше
PJPEG может уменьшить размер файла на 2−10% по сравнению с базовым/простым JPEG для изображений более 10 КБ. Более высокий коэффициент сжатия достигается благодаря тому, что на каждом проходе может составляться отдельная таблица Хаффмана [83]. Современные JPEG-кодеры (например, libjpeg-turbo [88], MozJPEG и др.) используют гибкость PJPEG для лучшего сжатия данных.
Примечание: почему PJPEG сжимает лучше? Потому что блоки базового JPEG кодируются по одному, а в PJPEG коэффициенты дискретного косинусного преобразования [89] из нескольких блоков можно кодировать вместе, что приводит к лучшему сжатию.
Многие другие сайты с большим количеством графических файлов, такие как Pinterest [92], тоже используют прогрессивный JPEG в продакшне.
На сайте Pinterest изображения кодируются только в прогрессивном JPEG. Для пользователей удобнее, когда картинка проявляется постепенно
Декодирование PJPEG медленнее, чем базового JPEG — иногда втрое медленнее. На десктопных машинах с мощными процессорами это не так важно, как на мобильных устройствах с ограниченными ресурсами. Отображение неполных слоёв требует работы, поскольку вы фактически декодируете изображение несколько раз. Эти множественные проходы съедают циклы CPU.
Также картинки в прогрессивном JPEG не всегда меньше по размеру. Прогрессивное кодирование очень маленьких изображений (например, миниатюр для предпросмотра) может увеличить их размер. И для таких картинок рендеринг в несколько проходов вообще имеет мало смысла.
Так что перед выбором PJPEG желательно поэкспериментировать и найти правильный баланс между размером файла, сетевой задержкой и использованием CPU.
Примечание: на мобильных устройствах может поддерживаться аппаратное декодирование PJPEG (и всех JPEG). Это не снижает потребление памяти, но уменьшает нагрузку на процессор. Не во всех смартфонах Android есть аппаратное ускорение, но в устройствах высокого класса и в устройствах iOS оно есть.
Некоторые пользователи могут считать прогрессивную загрузку недостатком, так как она мешает понять, когда завершилась загрузка изображения. Попробуйте оценить, как к этому относится ваша аудитория.
Инструменты и библиотеки вроде ImageMagick [93], libjpeg [94], jpegtran [84], jpeg-recompress [95] и imagemin [1] поддерживают прогрессивный 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
Наши глаза хуже замечают потерю цветности, чем яркости. Цветовая субдискретизация [96] (chroma subsampling) — вид компрессии, снижающий точность цветопередачи за счёт яркости (luma). Это уменьшает размер файла до 15−17% [97], не влияя заметно на качество изображения. Субдискретизация также уменьшает использование памяти.
Контраст отвечает за резкость на картинке, поэтому luma очень важна. На чёрно-белых фотографиях нет цвета, но благодаря яркости они выглядят такими же детальными, как цветные аналоги. Цветность меньше влияет на зрительное восприятие.
JPEG поддерживает различные типы подвыборки: отсутствие подвыборки, горизонтальная, горизонтальная+вертикальная. Здесь иллюстрация из статьи «JPEG для крабов» [98] Фредерика Кайзера
При обсуждении подвыборки обычно приводят ряд распространённых примеров: 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» [99] рекомендует придерживаться субдискретизации 4:4:4 (1×1)
Кстати: в спецификациях JPEG не указан точный метод цветовой субдискретизации, поэтому разные кодеры/декодеры поступают по-разному. MozJPEG и libjpeg-turbo используют один метод, а более старые версии libjpeg — другой, который добавляет артефактов.
Примечание: Photoshop автоматически выбирает цветовую субдискретизацию при «сохранении для веба». Если качество установлено в диапазоне 51−100, то субдискретизация не используется (4:4:4). Когда качество ниже, устанавливается 4:2:0. Это одна из причин, почему размер файла резко уменьшается при переключении качества с 51 на 50.
Примечание: в обсуждении субдискретизации часто упоминается термин YCbCr [100]. Это модель цветового пространства RGB [101] с гамма-коррекцией. Y — это яркость с гамма-коррекцией, Cb — компонент chroma синего цвета, а Cr — красного. Если посмотреть ExifData, вы увидите YCbCr рядом с уровнями выборки.
Дополнительные сведения см. в статье «Почему вы не используете цветовую субдискретизацию?» [97]
tl;dr: поддержка в браузерах сильно отличается. Если использовать современные разработки, то часто придётся выдавать разным браузерам разные форматы.
Различные современные форматы (и оптимизаторы) показывают качество сжатия при целевом размере файла 26 КБ. Качество сравнивается инструментами SSIM [102] (структурное сходство) и Butteraugli [103], которые мы более подробно рассмотрим позже.
Если вам нравится воспринимать информацию в графическом виде, можете оценить один [116] из этих [117] инструментов визуального сравнения для некоторых из вышеперечисленных форматов.
Таким образом, поддержка в браузерах сильно отличается. Чтобы использовать любой из вышеперечисленных форматов, вероятно, придётся выдавать разные копии каждому из целевых браузеров. Мы в Google видим определённые перспективы WebP, поэтому вскоре разберём подробнее этот формат.
Вы также можете выдавать разные форматы (например, WebP, JPEG 2000) с одним и тем же расширением .jpg (или любым другим) поскольку браузер может выбрать content-type для рендеринга независимо от расширения. Это позволяет указать content-type [118] на стороне сервера, вообще не меняя HTML-документ. Сервисы вроде Instart Logic используют такой подход.
Далее поговорим о ситуациях, когда нельзя выдавать изображения в разных форматах: здесь помогут JPEG-оптимизаторы.
Современные кодеки JPEG пытаются уменьшить размер файлов JPEG, максимально сохраняя качество и совместимость с существующими браузерами и приложениями. Они избавляют от необходимости использовать новые форматы изображений и вносить изменения в экосистему. Два таких энкодера — MozJPEG и Guetzli.
tl;dr: Какой JPEG-кодек с оптимизацией использовать?
Mozilla предлагает модернизированный JPEG-кодер — MozJPEG [15]. По заявлению [119] разработчиков, он уменьшает размер файлов JPEG до 10%. Файлы, сжатые MozJPEG, открываются во всех браузерах, а среди поддерживаемых функций — прогрессивное сканирование, треллис-квантование [120] (удаление деталей, которые хуже всего сжимаются) и несколько продвинутых шаблонов таблиц квантования [121], которые помогают создавать более гладкие изображения High-DPI (хотя это возможно с ImageMagick, если вы готовы пробираться через дебри XML-конфигурации).
MozJPEG поддерживается в ImageOptim [122] и для него есть относительно надёжный настраиваемый плагин imagemin [123]. Вот пример реализации с помощью 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 [124] из проекта jpeg-archive [95].
По моему опыту, MozJPEG — хороший вариант сжатия изображений для интернета с высоким качеством при одновременном уменьшении размера файла. Для изображений малого и среднего размера MozJPEG (с качеством 80−85) уменьшает файлы на 30−40% с сохранением приемлемого SSIM и улучшением на 5−6% по jpeg-turbo. Он кодирует медленнее базового JPEG [125], но разница не критична.
Примечание: если вам нужен инструмент, поддерживающий MozJPEG с дополнительной конфигурацией и некоторыми бесплатными утилитами для сравнения изображений, посмотрите на jpeg-recompress [95]. Автор книги «Веб-производительность в действии» Джереми Вагнер с успехом использовал программу в такой [126] конфигурации.
Guetzli [127] — многообещающий, но очень медленный, перцептивный JPEG-кодек от Google. Он пытается найти самый маленький JPEG, перцептивно неотличимый от оригинала. Кодек выполняет ряд экспериментов, предлагая варианты для сравнения, и учитывает психовизуальную ошибку каждого варианта. В качестве конечного результата выбирается вариант с наивысшей оценкой.
Для измерения различия между изображениями Guetzli применяет Butteraugli [103] — модель на основе человеческого восприятия (обсуждается ниже). Guetzli учитывает некоторые свойства человеческого зрения, которые не принимаются в расчёт другими кодеками JPEG. Например, существует зависимость между количеством видимого зелёного света и чувствительностью к синему, поэтому изменения синего цвета около зелёного можно кодировать менее точно.
Примечание: Размер файла намного сильнее зависит от выбора уровня кодирования, чем от выбора кодека. Между низким и высоким уровнями качества в формате JPEG намного, намного бóльшая разница, чем при смене кодека. Очень важно указать минимально приемлемый уровень качества. Обязательно обращайте внимание на этот показатель, чтобы он не оказался слишком высоким.
Guetzli заявляет [22] о разнице в размере файлов 20−30% без уменьшения оценки Butteraugli по сравнению с другими компрессорами. Большой недостаток Guetzli в его чрезвычайной медлительности, так что в настоящее время он подходит только для статического контента. В README указан большой объём потребляемой памяти: кодирование требует около 1 минуты и 200 МБ RAM на мегапиксель. На GitHub есть хороший тред [128] с обсуждением реального опыта работы с Guetzli. Кодек идеально подходит для оптимизации изображений при сборке статического сайта, но в меньшей степени пригоден для запуска по требованию.
Инструменты вроде ImageOptim поддерживают оптимизацию Guetzli (в последних версиях [13]).
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 может привнести «жидкоподобные» искажения.
Для разнообразия вариантов использования вас может заинтересовать сравнение [129] Guetzli с автоматическим сжатием Cloudinary в исследовании Эрика Портиса.
Сложно сравнивать разные кодеки JPEG: необходимо оценить и качество, и точность сжатого изображения, а не только размер. Как отмечает эксперт по сжатию изображений Корнель Лесински, бенчмарк только одного, а не обоих аспектов, может привести к неверным [130] выводам.
Как выглядят Guetzli и MozJPEG в сравнении? Подход Корнеля:
Существует ряд методов определения визуального или перцептивного сходства сжатых изображений с исходником. В исследованиях часто используется SSIM [102] (структурное сходство). Однако Guetzli оптимизирован для Butteraugli.
Система Butteraugli определяет момент, когда человек начинает замечать разницу (психовизуальное сходство) между двумя изображениями. Butteraugli не только даёт оценку, но и составляет пространственную карту уровня различий. В то время как SSIM суммирует все ошибки, Butteraugli ищет максимальные.
В этом примере Butteraugli ищет минимальный порог качества JPEG, чтобы пользователь не заметил визуальной разницы между изображениями. Это позволило уменьшить размер файла на 65%
На практике вы определяете уровень визуального качества, а затем запускаете несколько стратегий оптимизации изображений, глядя на оценки Butteraugli, прежде чем выбрать результат, который соответствует оптимальному балансу размера файла и уровня сжатия.
Мне потребовалось около 30 минут для локальной настройки Butteraugli после установки Bazel и сборки исходников C++ для корректной компиляции на Mac. Его использование относительно простое: укажите два изображения для сравнения (исходная и сжатая версия) — и получите оценку
Один из разработчиков Guetzli говорит [131], что Guetzli лучше по оценке Butteraugli, хуже по SSIM, а MozJPEG примерно одинаково хорош по обеим метрикам. Это стратегию я использую для оптимизации изображений. Я запускаю Butteraugli и модуль Node вроде img-ssim [132] для сравнения оценок SSIM до/после Guetzli и MozJPEG.
Как показала практика, сочетание Guetzli и MozJPEG без потерь (jpegtran, а не cjpeg, чтобы не отбрасывать работу, проделанную Guetzli) позволяет дополнительно уменьшить размер файла на 10−15% (55% в целом) с весьма незначительным снижением оценки SSIM. Это требует проверки и анализа, но другие специалисты вроде Арии Хидаята [133] попробовали — и получили такой же многообещающий результат.
MozJPEG — удобный кодек для новичков, который сравнительно быстро сжимает файлы для веба и обеспечивает хорошее качество изображения. В то же время Guetzli ресурсоёмок и лучше всего работает на больших, высококачественных изображениях: этот вариант я бы рекомендовал продвинутым и профессиональным пользователям.
WebP — последний графический формат от Google, который стремится уменьшить размеры файлов при сжатии без потерь и с потерями, обеспечивая приемлемое визуальное качество. Поддерживает альфа-канал (прозрачность) и анимацию.
WebP совершенствуется: за прошлый год он прибавил несколько процентов в сжатии без потерь и с потерями, по скорости кодирования стал вдвое быстрее, а скорость декодирования увеличилась на 10%. WebP — не универсальный инструмент, но его популярность растёт. Давайте рассмотрим, почему.
WebP: сравнение размеров файлов и оценки визуального сходства на разных уровнях качества
Разработчики говорят, что при сжатии с потерями с использованием кодека VP8 или VP9 файлы уменьшаются в среднем на 25−34% [134] по сравнению с JPEG.
В диапазоне низкого качества (0−50) у WebP большое преимущество перед JPEG, поскольку он размывает уродливые артефакты блочности. Настройка среднего качества (-m 4 -q 75) — установленный по умолчанию баланс скорости и размера файла. В диапазоне высокого качества (80−99) преимущества WebP минимальны. WebP рекомендуется там, где скорость важнее качества.
Файлы WebP со сжатием без потерь на 26% меньше файлов PNG [135]. Время загрузки по сравнению с 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 в продакшне для снижения расходов и увеличения скорости загрузки страницы.
Google сообщил об экономии 30−35% на WebP по сравнению с другими схемами сжатия с потерями. Google выдаёт 43 миллиарда изображений в день, 26% из которых сжаты без потерь. Это много запросов и значительная экономия. Несомненно, она ещё увеличится, когда браузеры улучшат поддержку WebP [136]. Google использует этот формат на Google Play, YouTube и других сайтах.
Netflix, Amazon, Quora, Yahoo, Walmart, Ebay, The Guardian, Fortune и USA Today сжимают и выдают изображения WebP для браузеров, которые его поддерживают. Издатель VoxMedia на 1−3 секунды уменьшил время загрузки страниц [137] The Verge, перейдя на WebP для пользователей Chrome. Сайт 500px [138] зафиксировал уменьшение размеров файлов в среднем на 25% с аналогичным или лучшим качеством.
Кроме вышеперечисленных, WebP используют и другие компании.
Использование WebP в Google: 43 миллиарда картинок WebP ежедневно выдаются на YouTube, Google Play, Chrome Data Saver и G+
Для статических изображений WebP — альтернатива JPEG. В кодировании с потерями три ключевых этапа:
Macro-blocking — разделение изображения на (макро) блоки по 16×16 пикселей яркости и на блоки по 8×8 пикселей цветности. Это похоже на то, как JPEG преобразует цветовое пространство, разбивая его на блоки и понижая количество пикселей на каналах цветности.
Прогнозирование — для каждого подблока 4×4 составляется модель прогнозирования, которая эффективно выполняет фильтрацию. Её определяют два набора пикселей вокруг блока: A (строка непосредственно сверху) и L (столбец слева). С помощью этих двух наборов энкодер заполняет пикселями тестовый блок 4×4 и определяет, какие значения ближе всего к исходному блоку. Кольт Маканлис более подробно рассказывает об этом в статье [139] о том, как работает WebP в режиме сжатия с потерями.
Дискретное косинусное преобразование (DCT) применяется в несколько этапов, как в JPEG. Ключевое отличие — использование арифметического сжатия [140], а не алгоритма Хаффмана, как в JPEG.
Для дополнительной информации рекомендую статью «Методы сжатия WebP» [141] с сайта Google Developer.
Не все браузеры поддерживают WebP, но по данным CanIUse.com [142], глобальная поддержка составляет около 74%. Chrome и Opera поддерживают формат. Safari, Edge и Firefox экспериментируют, но пока не реализовали поддержку в официальных версиях. Из-за этого выдача WebP зачастую зависит от веб-разработчика. Подробнее об этом позже.
Вот основные браузеры и информация о поддержке каждым из них:
WebP не лишён недостатков. В нём отсутствуют опции цветового пространства с полным разрешением и не поддерживается прогрессивное декодирование. Тем не менее, для WebP создан приличный инструментарий, а поддержки браузеров вполне хватает, чтобы рассматривать выдачу WebP как один из вариантов.
Несколько коммерческих и свободных редакторов поддерживают WebP. Одно из самых полезных приложений — XnConvert: это бесплатный кросс-платформенный пакетный конвертер.
Примечание: важно не допускать преобразования в WebP картинок JPEG низкого или среднего качества. Это распространённая ошибка, в результате которой генерируются изображения WebP с артефактами сжатия JPEG. Это снижает эффективность WebP, поскольку ему приходится сохранять и изображение, и искажения JPEG, что приводит к двойной потере качества. Загружайте в конвертер файл максимального качества, желательно оригинал.
XnConvert [143] производит пакетную обработку изображений более чем 500 форматов. Вы можете объединить разными способами более 80 отдельных действий для преобразования или редактирования изображений.
XnConvert поддерживает пакетную оптимизацию изображений, выполняя прямое преобразование из исходных файлов в WebP и другие форматы. Кроме сжатия, XnConvert умеет удалять метаданные, обрезать картинки, настраивать глубину цвета и выполнять другие преобразования
Некоторые параметры, перечисленные на веб-сайте xnview:
Результаты операций можно экспортировать примерно в 70 различных форматов файлов, включая WebP. XnConvert — бесплатная программа под Linux, Mac и Windows. Это отличный вариант, особенно для малого бизнеса.
Imagemin [1] — популярный модуль сжатия изображений, у которого есть расширение для преобразования в WebP (imagemin-webp [144]). Поддерживается сжатие с потерями и без потерь.
Для установки 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 [145] от Синдре Сорхуса сделан на базе imagemin-webp, есть ещё загрузчик WebP для WebPack [146]. Плагин 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'))
);
XNConvert поддерживает пакетное сжатие, но всё можно сделать из командной строки.
Пакетная конвертация изображений в формат WebP с помощью cwebp [147]:
find ./ -type f -name '*.jpg' -exec cwebp -q 70 {} -o {}.webp ;
Оптимизация кодеком MozJPEG с использованием jpeg-recompress [95]:
find ./ -type f -name '*.jpg' -exec jpeg-recompress {} {} ;
и обрезка SVG с помощью программы svgo [18] (которую мы рассмотрим позже):
find ./ -type f -name '*.svg' -exec svgo {} ;
Джереми Вагнер написал более полную статью по оптимизации изображений в Bash [148] и ещё одну — о распараллеливании [149] этой задачи.
Для Android вы можете конвертировать существующие BMP, JPG, PNG и статические GIF-изображения в формат WebP с помощью Android Studio. Дополнительные сведения см. в разделе «Создание изображений WebP с помощью Android Studio» [150].
Хотя изображения WebP всегда открываются в браузере на движке Blink (Chrome, Opera, Brave), их можно просматривать непосредственно из ОС с помощью надстройки для Mac или Windows.
Несколько лет назад Facebook экспериментировал с WebP [151] и заметил проблему: некоторые пользователи сохраняли картинки на диск, а потом не могли их открыть. Здесь три ключевые проблемы:
У ваших пользователей такие проблемы могут не проявиться, но это интересная заметка на полях. К счастью, сегодня существуют утилиты для просмотра WebP под разные ОС.
На Mac попробуйте плагин Quick Look для WebP [152] (qlImageSize). Он неплохо работает:
Под Windows можно загрузить пакет кодеков WebP [153], который добавляет опцию просмотра WebP в File Explorer и Windows Photo Viewer.
Браузеры без поддержки WebP не покажут никакой картинки. Чтобы избежать этого, есть несколько стратегий.
Панель Chrome DevTools Network с выделением файлов типа WebP, которые отдаются в браузеры на движке Blink
Play Store отдаёт WebP браузерам на Blink и JPEG остальным, таких как Firefox
Вот некоторые варианты доставки изображений WebP пользователям:
Вот как использовать .htaccess для выдачи файлов WebP в поддерживаемых браузерах, если на сервере есть webp-версия файла JPEG/PNG.
Винсент Орбак рекомендовал такой подход:
Браузеры могут явно сигнализировать о поддержке WebP [154] через заголовок Accept [155]. В этом случае вы можете отдать с сервера 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 [156] для выдачи WebP, а Илья Григорик поддерживает коллекцию скриптов конфигурации для выдачи WebP [157], которые могут быть полезны.
Браузер сам способен выбирать формат изображения с помощью тега <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>
Некоторые CDN поддерживают автоматическое преобразование и выдачу WebP по запросу клиента, когда это возможно [158]. Проверьте свой CDN, есть ли у них поддержка. Возможно, проблема очень просто решается.
Jetpack: популярный плагин WordPress, включает в себя CDN-сервис изображений под названием Photon [159] с поддержкой WebP. Он включён в бесплатную версию Jetpack, что очень практично и полезно. Недостаток в том, что Photon автоматически изменяет размеры изображения, помещает строку запроса в URL, а для каждого изображения выполняется дополнительный запрос к DNS.
Cache Enabler и Optimizer: если вы используете WordPress, есть как минимум один вариант с открытым исходным кодом. В меню плагина Cache Enabler [160] есть флажок для кэширования и выдачи изображений WebP, если браузер пользователя их поддерживает. Это упрощает работу с WebP. Здесь тоже недостаток: Cache Enabler требует использования родственной программы Optimizer, за которую взимают ежегодную плату. Это не очень характерно для решений с открытым исходным кодом.
Short Pixel: другой вариант оптимизатора для Cache Enabler, тоже платный. По функциональности Short Pixel очень похож на упомянутый Optimizer. Позволяется бесплатно оптимизировать до 100 фотографий в месяц.
Анимированные GIF по-прежнему широко используются, несмотря на их узкую специализацию. Хотя все, от социальных сетей до популярных медиа-сайтов, обильно использую GIF-анимацию, этот формат никогда не предназначался для видео или анимации. На самом деле спецификация GIF89a [161] явно указывает, что «GIF не предназначен служить платформой для анимации». Количество цветов, количество кадров и пропорции [162] — всё это влияет на размер анимированного GIF. Замена на видеоформат даёт максимальную экономию.
Сравнение размеров GIF-анимации и видео в эквивалентном качестве
Выдача того же видео в формате MP4 сокращает размер файла на 80% или больше. Кроме того, что файлы GIF впустую тратят трафик, они дольше загружаются, содержат меньше цветов и обычно выглядят не очень приятно. Возможно, вы обратили внимание, что загруженные в Twitter анимации GIF работают там лучше, чем на других сайтах. Это потому что анимированные GIF в Twitter на самом деле не являются GIF-файлами [163]. Чтобы улучшить качество и уменьшить трафик, Twitter автоматически преобразует их в видео. Аналогично, Imgur при загрузке конвертирует GIF в MP4 [164].
Почему GIF-файлы во много раз больше про размеру? Потому что они хранят каждый кадр как GIF-изображение без потерь — да, без потерь. Плохое качество GIF вызвано не сжатием, а палитрой в 256 цветов. Формат не анализирует соседние кадры для сжатия, в отличие от видеокодеков вроде H.264. Видео MP4 хранит каждый ключевой кадр как JPEG с потерями, отбрасывая часть исходных данных для достижения лучшего сжатия.
ffmpeg -i animated.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)2:trunc(ih/2)2" video.mp4
-lossy
и сжимает анимацию на 60−65%. На его основе сделан хороший инструмент Gifify [167]. Неанимированные GIF преобразуйте в формат PNG или WebP.Для получения дополнительной информации см. «Книгу GIF» [168] от Rigor.
Минимизировать файлы SVG — значит удалить всё лишнее. Как правило, SVG из редактора содержит много избыточной информации (метаданные, комментарии, скрытые слои и так далее). Зачастую её можно безопасно удалить или свести к минимуму, не влияя на визуальный результат.
В сервисе SVGOMG [169] от Джейка Арчибальда можно выбрать разные способы оптимизации с мгновенным просмотром результата
<rect>
, <circle>
, <ellipse>
, <line>
и <polygon>
. Это уменьшит объём необходимой разметки и объём кода для парсинга и растеризации в браузере.
Эффективность SVGO в режиме высокой точности (−29% от размера оригинального файла) и низкой точности (−38%)
SVGO [18] — инструмент оптимизации SVG на Node. Он уменьшает размер файла, понижая точность чисел в definitions. Каждая цифра после точки — лишний байт, поэтому изменение точности (количества цифр) сильно влияет на размер файла. Но будьте очень осторожны, потому что снижение точности может визуально повлиять на формы изображения.
Важно отметить: хотя SVGO преуспел в предыдущем примере без чрезмерного упрощения путей и форм, часто случается иначе. Посмотрите, как с понижением точности искажается блик на ракете
SVGO можно установить как CLI [172], если вы предпочитаете командную строку:
npm i -g svgo
Оптимизация SVG-файла:
svgo input.svg -o output.svg
Поддерживаются все возможные параметры, включая настройку точности с плавающей точкой:
svgo input.svg --precision=1 -o output.svg
См. readme [18] для полного списка поддерживаемых параметров.
Кроме того, не забудьте зазиповать файлы SVG [173] или выдавать их по протоколу Brotli. Текстовый формат будет очень хорошо сжиматься (~50% от исходника).
Когда Google выпустила новый логотип, мы объявили, что его минимальная [174] версия занимает всего 305 байт.
Есть много продвинутых трюков [175], чтобы ещё сильнее ужать файл (вплоть до 146 байт)!
SVG отлично подходит [176] для иконок, предлагая визуализацию в виде спрайта без изворотливых обходных путей, необходимых для шрифтов. У него лучший контроль стилей CSS, чем в шрифтах (свойства SVG stroke), лучший контроль позиционирования (нет необходимости заморачиваться с псевдоэлементами и display
) и SVG гораздо лучше поддерживается в браузерах [177].
Инструменты вроде svg-sprite [178] и IcoMoon [179] автоматизируют объединение SVG в спрайты, которые можно использовать в CSS Sprite [180], Symbol Sprite [181] или Stacked Sprite [182]. Стоит изучить практичные советы [183] от Уны Кравец, как использовать gulp-svg-sprite в рабочем процессе. Сара Судеин в своём блоге описывает переход от шрифтов для иконок к SVG [184].
Советы Сары Соуэйдан по оптимизации выдачи SVG [173] и «Практическая книга по SVG» [185] Криса Койера превосходны. Я нашёл очень полезными статьи Андреаса Ларсена об оптимизации SVG (часть 1 [186], часть 2 [187]). Могу также порекомендовать статью «Подготовка и экспорт значков SVG в Sketch» [188].
Сжимать изображение всегда рекомендуется из исходника. Повторное пережатие чревато неприятными последствиями. Предположим, вы берете JPEG, который уже сжат с качеством 60. Если повторно сжать его с потерями, он будет выглядеть хуже. Каждый дополнительный раунд сжатия приведёт к дополнительной потере качества — информация удаляется, а артефакты накапливаются. Даже если вы пережимаете с установками высокого качества.
Чтобы избежать этой ловушки, сразу установите минимально приемлемое качество, и получите максимальную экономию с самого начала. Затем вы не пойдёте на повторное пережатие, потому что любое сжатие файла с потерями будет выглядеть плохо, хотя и уменьшит размер файла.
Пример из отличного видео [189] и сопроводительной статьи [190] Джона Снейерса показывает влияние пережатия в разных форматах. С такой проблемой можно столкнуться, если сохранять (уже сжатые) картинки из социальных сетей и повторно загружать их (с повторным сжатием). Потеря качества нарастает
MozJPEG (возможно, случайно) более устойчив к такой деградации благодаря треллис-квантованию. Вместо сжатия всех значений DCT как есть он ищет близкие значения в диапазоне +1/-1, чтобы сжать их в меньшем количестве бит. FLIF с потерей качества использует хак, похожий на PNG с потерей качества, где перед (повторным) сжатием кодек анализирует данные и решает, что выбросить.
Исходные файлы храните их в формате без потерь, например, PNG или TIFF, чтобы сохранить максимальное качество. Затем инструменты сборки или компрессоры подготовят сжатую версию, которую вы отдадите пользователям с минимальными потерями в качестве.
Все мы отдавали пользователям большие изображения со слишком высоким разрешением. За это приходится платить. Декодирование и изменение размера — ресурсоёмкие операции для браузера на обычном мобильнике. Если отдавать большие изображения, масштабируя их средствами CSS или атрибутами ширины/высоты, то вы увидите, как это повлияет на производительность.
Когда браузер получает изображение, он должен декодировать его из исходного исходного формата (например, JPEG) в растровое изображение в памяти. Часто изображение требует изменения размера (например, ширина установлена в процентах). Декодирование и изменение размера изображений — ресурсоёмкие операции, которые замедляют рендеринг
В идеале следует отдавать изображения, которые браузер отобразит без изменения размера. Так что отдавайте картинки минимального размера для соответствующих экранов и разрешений, используя srcset/sizes
[191] — в ближайшее время мы рассмотрим srcset
.
Пропуск атрибутов width
или height
тоже может негативно повлиять на производительность. Без них браузер присваивает изображению наименьшую область-заполнитель, пока не получит достаточное количество байт для определения правильных размеров. В этот момент разметку документа приходится обновлять с помощью ресурсоёмкой операции reflow.
Браузерам нужно совершить несколько шагов, чтобы отрисовать картинку на экране. Получив изображение, его необходимо декодировать и зачастую изменить размер. Эти события можно отследить на временной шкале [192] Chrome DevTools
Большие изображения также занимают память: примерно по 4 байта на пиксель после декодирования. Если вы не слишком аккуратны, то можете буквально повесить браузер; на низкобюджетных устройствах не так уж сложно довести ситуацию до свопа. Таким образом, следите за издержками на декодирование, изменение размера и потребление памяти.
Декодирование изображений может оказаться невероятно ресурсоёмким на мобильных телефонах среднего и нижнего уровня. В некоторых случаях оно в 5 и более раз медленнее, чем на десктопе
При разработке новой мобильной версии [193] Twitter сильно повысил скорость декодирования изображений, установив правильные размеры. Для многих изображений время декодирования снизилось с от ~400 мс до ~19 мс!
Панель Timeline/Performance в Chrome DevTools показывает время декодирования изображения в Twitter Lite до и после оптимизации
srcset
Пользователи могут заходить на сайт через разные мобильные и десктопные устройства с экранами высокого разрешения. Соотношение пикселей устройства [194] (DPR) (также называемое «соотношение пикселей CSS») определяет, как CSS должен интерпретировать разрешение экрана. Стандарт DPR создан производителями телефонов, чтобы увеличить разрешение и резкость мобильных экранов, не уменьшая элементы.
Для максимального качества следует отдавать изображения с наиболее подходящим разрешением. На устройства с экранами высокого разрешения отдаются изображения высокой чёткости (с DPR 2×, 3×), а на стандартные экраны — обычные изображения, так как картинки с DPR 2× и 3× значительно тяжелее.
Соотношение пикселей устройства: многие сайты отслеживают DPR популярных устройств через material.io [195] и mydevice.io [196]
srcset [191] позволяет браузеру выбрать оптимальное изображение для каждого устройства. Например, взять картинку 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 [197] и Imgix [198] поддерживают DPR для выдачи картинки с оптимальным разрешением из одного источника.
Примечание: узнать больше о соотношении пикселей устройства и отзывчивых изображениях можно в этом бесплатном курсе Udacity [199] и руководстве по изображениям [200] на Web Fundamentals.
Напоминаю, что Client Hints [201] — тоже подходящая альтернатива указанию всех возможных DPR и форматов в отзывчивой разметке. Вместо этого соответствующая информация добавляется к HTTP-запросу, чтобы веб-сервер выбрал наиболее подходящий вариант для конкретного экрана.
Хотя выбор правильного разрешения важен, некоторые сайты думают ещё о красоте. Если у пользователя маленький экран, можно обрезать или увеличить масштаб — и отобразить объект иначе, наилучшим образом используя доступное пространство. Хотя художественное преобразование [202] (art direction) выходит за рамки этой статьи, некоторые сервисы вроде Cloudinary [203] предоставляют API-интерфейсы для автоматизации таких задач.
Эрик Портис показал отличный пример [204], как творчески использовать отзывчивые изображения. В этом примере характеристики основного объекта на иллюстрации изменяются, чтобы наилучшим образом использовать доступное пространство
Цвет можно рассматривать минимум с трёх перспектив: биология, физика и печать. В биологии цвет — феномен восприятия [205]. Объекты отражают свет в различных комбинациях длин волн. Световые рецепторы в глазах переводят эти волны в ощущение цвета. В физике важны частоты волн и энергия (яркость). Печать — это больше о цветовом охвате, красках и художественных моделях.
В идеале, все экраны и веб-браузеры в мире должны в точности одинаково отображать цвет. К сожалению, это не так. Управление цветом позволяет достичь компромисса в отображении цветов с помощью цветовых моделей, пространств и профилей.
Цветовые модели [206] — это система для создания полного спектра из меньшего набора основных цветов. Есть различные типы цветовых пространств с разными параметрами для управления цветами. В некоторых пространствах меньше управляющих параметров, чем в других — например, для всех оттенков серого достаточно одного параметра яркости между чёрным и белым.
Два распространённых типа цветовых моделей — аддитивные и субтрактивные. Аддитивные цветовые модели типа RGB отображают цвет свечением, а субтрактивные типа CMYK — отражением (вычитанием).
В RGB красный, зелёный и синий свет добавляются в различных сочетаниях для получения широкого спектра цветов. CMYK (циан, маджента, жёлтый и чёрный) работает чернилами разного цвета, отнимая часть белого спектра бумаги
Статья «Понятие цветовых моделей и систем цвета» [207] хорошо описывает другие цветовые модели и режимы, такие как HSL, HSV и LAB.
Цветовые пространства [208] — это определённый диапазон цветов, которые можно отобразить для данного изображения. Например, в изображении до 16,7 миллиона цветов, а различные цветовые пространства позволяют сузить или расширить этот диапазон. Некоторые разработчики считают, что цветовые модели и цветовые пространства — это одно и то же.
sRGB [209] разработан на основе RGB как стандарт [210] для интернета. Это небольшое цветовое пространство, которое обычно считают наименьшим общим знаменателем и самым безопасным вариантом для управления цветом в браузерах. Другие цветовые пространства (например, Adobe RGB [211] или ProPhoto RGB [212], используемые в Photoshop и Lightroom) содержат более разнообразные цвета, но поскольку sRGB распространён в браузерах, играх и мониторах, обычно используют именно его.
Визуализация гаммы — диапазона цветов в цветовом пространстве
В цветовых пространствах используется три канала (красный, зелёный и синий), в каждом по 255 цветов в 8-битном режиме, что даёт 16,7 миллиона цветов. 16-битные картинки спосбоны отображать триллионы цветов.
Сравнение sRGB, Adobe RGB и ProPhoto RGB на изображении с Yardstick [213]. Невероятно трудно проиллюстрировать эту концепцию, если ваш экран показывает только цвета sRGB. При сравнении обычной фотографии в sRGB и широкой гамме всё будет одинаково, кроме самых насыщенных «сочных» цветов
Цветовые пространства отличаются своей гаммой (диапазон цветов, которые они могут воспроизводить с оттенками), спектром и гамма-кривой [214]. sRGB примерно на 20% меньше, чем Adobe RGB, ProPhoto RGB примерно на 50% шире [215], чем Adobe RGB. Фотографии выше взяты с Clipping Path [216].
Широкая гамма [217] (wide-gamut) — это термин, означающий цветовые пространства шире sRGB. Такие типы дисплеев становятся всё более распространёнными. Тем не менее, многие цифровые дисплеи по-прежнему просто не способны отображать цветовые профили, которые значительно лучше sRGB. При сохранении для веба в Photoshop используйте опцию преобразования в sRGB, если только не рассчитываете на дисплеи с широкой цветовой гаммой.
Примечание: При работе с оригинальными фотографиями не используйте sRGB в качестве основного цветового пространства. Оно меньше, цветовых пространств в большинство камер и может привести к потере информации. Вместо этого работайте с широким цветовым пространством (например, ProPhoto RGB), в конвертируйте в sRGB только при экспорте для интернета.
Да. Если изображение содержит очень насыщенный/сочный/яркий цвет — и вы хотите отобразить его на совместимых экранах. Впрочем, на реальных фотографиях такое редко случается. Зачастую можно легко подкрутить настройки, чтобы цвет выглядел ярким, не выходя за рамки гаммы sRGB.
Причина в том, что человеческое восприятие цвета не абсолютно. Восприятие работает относительно окружения — и его легко обмануть. Но если на картинке след флуоресцентного маркера, то конечно, легче его показать в широкой гамме.
Гамма-коррекция [206] (или просто гамма) управляет общей яркостью изображения. Изменение гаммы также может изменить соотношение красного и зелёного цветов. Изображения без гамма-коррекции часто выглядят блеклыми или тёмными.
В видео и компьютерной графике гамма используется для сжатия, аналогично сжатию данных. Это позволяет сжать полезные уровни яркости в меньшем количестве бит (8, а не 12 или 16). Человеческое восприятие яркости нелинейно пропорционально физическому количеству света. Представление цветов в их истинной физической форме было бы расточительным при кодировании для человеческого глаза. Гамма-сжатие (gamma compression) используется для кодирования яркости в масштабе, более близком человеческому восприятию.
С гамма-сжатием полезная шкала яркости умещается в 8 бит точности (0−255 в большинством цветов RGB), потому что единицы яркости кодируются нелинейно. Представьте, что вы находитесь в тёмной комнате с одной свечой. Зажгите вторую — и заметите значительное увеличение яркости. Добавьте третью свечу, и комната станет ещё ярче. А теперь представьте себя в комнате с сотней свечей. Зажгите 101-ю, 102-ю свечи — и вы не заметите никаких изменений.
В обоих случаях физически добавили одинакового количество света. Но поскольку глаза менее чувствительны к яркому свету, гамма-компрессия «сжимает» яркие значения, поэтому в физических единицах там кодируется меньшая точность, но сам масштаб скорректирован для людей — и с человеческой точки зрения все значения одинаково точны.
Примечание: Гамма-коррекция или сжатие здесь отличаются от гамма-кривых в «Фотошопе», правильное гамма-сжатие ни на что не похоже.
Цветовой профиль — это информация, описывающая цветовое пространство устройства. Он используется для преобразования между различными цветовыми пространствами. Задача профилей — чтобы изображения были максимально похожи на всех типах экранов и носителей.
Изображения могут иметь встроенный цветовой профиль по стандарту Международного цветового консорциума [218] (ICC), чтобы точно определить цвета. Профили поддерживаются в разных форматах, включая JPEG, PNG, SVG и WebP, и большинство основных браузеров тоже поддерживают встроенные профили ICC. Если картинка открывается в программе и известен профиль монитора, то цвета корректируются соответствующим образом.
Примечание: Цветовые профили некоторых мониторов аналогичны sRGB, так что они не смогут отобразить цвета из более широкой гаммы. Поэтому внедрение цифровых профилей в изображения может быть ограничено. Учитывайте особенности своей целевой аудитории.
Встроенные цветовые профили также значительно увеличивают размер изображений (иногда на 100 КБ и больше), поэтому будьте осторожны. Инструменты вроде ImageOptim автоматически удаляют все цветовые профили, какие найдут. Если профиль ICC удалён, браузер начнёт отображать картинку в цветовом пространстве вашего монитора, что может привести к изменению насыщенности и контраста. Так что есть смысл поискать компромисс для каждого конкретного случая.
На сайте Nine Degrees Below [219] отличная подборка ресурсов по управлению цветовыми профилями ICC, если вам нужна дополнительная информация.
В прежних версиях Chrome не было особой поддержки управления цветом, но ситуацию исправили в 2017 году, внедрив функцию Color Correct Rendering [220]. Если профиль дисплея отличается от sRGB (последние MacBook Pro), то он преобразуют цвета из sRGB в профиль дисплея. Это означает, что цвета станут более похожими в разных системах и браузерах. Браузеры Safari, Edge и Firefox тоже учитывают профили ICC, поэтому изображения с разными профилями теперь отображаются корректно, независимо от того, у вас дисплей с широкой цветовой гаммой или нет.
Примечание: Отличное руководство о разнообразных способах использования цвета в вебе — «Справочник нерда по цвету в интернете» [221] Сары Дразнер.
У спрайтов изображений [222] (или CSS-спрайтов) долгая история, они поддерживаются всеми браузерами и были популярным способом уменьшить количество загружаемых картинок путём объединения их в одно более крупное изображение, которое нарезается на части.
Спрайты изображений по-прежнему широко используются на крупных сайтах в продакшне, включая главную страницу Google
По стандарту HTTP/1.x некоторые применяли спрайты для уменьшения количества HTTP-запросов. Это имело ряд преимуществ, но требовало аккуратности из-за проблемы с инвалидацией кэша — изменения любой небольшой части спрайта приведут к инвалидации всего изображения в кэше.
Сейчас разбиение на спрайты противоречит рекомендациям HTTP/2 [223]. Поскольку стало возможно отправлять много запросов в одном соединении, то лучше загружать картинки по отдельности [224]. Оцените варианты для своей ситуации.
Ленивая (отложенная) загрузка — это практика повышения производительности, когда загрузка изображений в браузер задерживается до тех пор, пока реально не понадобится пользователю. Например, картинки загружаются асинхронно при прокрутке страницы. Это может экономить трафик дополнительно к сжатию изображений.
Попадающие на экран картинки загружаются сразу. Но остальные в этот момент ещё не видны. Их следует загружать не сразу, а позже — это и есть ленивая загрузка. Она происходит только если и когда пользователь прокручивает страницу вниз.
Ленивая загрузка пока не поддерживается самими браузерами (хотя в прошлом такое обсуждалось [225]). Вместо этого используется JavaScript.
У неё много преимуществ:
Впрочем, как и с другими инструментами, с большой силой приходит большая ответственность.
Избегайте отложенной загрузки изображений в области видимости. Используйте её для длинных списков (например, продуктов или пользовательских аватар). Не применяйте её для главной картинки на странице. Ленивая загрузка в области видимости может замедлить загрузку как технически, так и для человеческого восприятия. Она убивает предзагрузку и прогрессивную загрузку, а JavaScript генерирует лишнюю работу для браузера.
Будьте очень осторожны с ленивой загрузкой изображений при прокрутке. Если ждать непосредственно события прокрутки, то пользователь может увидеть заполнители вместо картинок или получить картинки до скроллинга на них. Одна из рекомендаций — начинать ленивую загрузку следующих изображений сразу после того, как на экране отобразилось предыдущее, независимо от взаимодействия с пользователем.
Ленивую загрузку применяет большинство крупных сайтов с большим количеством изображений. Например, Medium [226] и Pinterest [227].
Пример превью с гауссовым размытием иллюстраций на Medium
На некоторых сайтах (например, Medium) для предварительного просмотра отображается небольшая размытая картинка (около 100 байт), которое после отложенной загрузки превращается в иллюстрацию нормального качества.
Хосе М. Перес рассказал, как реализовать эффект Medium с помощью CSS-фильтров [228]. Он экспериментировал с разными графическими форматами [229]. Facebook тоже описывал свой знаменитый подход [230] с 200-байтовыми заполнителями для заглавных фотографий. Если вы пользуетесь Webpack, то LQIP loader [231] поможет автоматизировать некоторые из этих процедур.
Чтобы увидеть ленивую загрузку, достаточно открыть любимый каталог качественных фотографий, а затем прокрутить страницу вниз. Почти всегда вы увидите, что сайт загружает только несколько картинок с полным разрешением, а остальное — заполнители. По мере прокрутки заполнители заменяются изображениями в полном разрешении. Это ленивая загрузка.
В последнее время получила распространение новая техника векторных, а не растровых заполнителей. Её предложил Тобиас Балдауф в своём инструменте SQIP [232]. Там утилита Primitive [233] генерирует SVG-превью из нескольких простых форм, примерные совпадающих с основными чертами изображения. Затем SVG оптимизируется с помощью SVGO [18] — и накладывается фильтр гауссова размытия. В результате получается заполнитель SVG размером всего 800−1000 байт, который выглядит чётким на любых экранах и даёт осмысленное представление, что находится на реальной картинке. Очевидно, можно комбинировать [234] ленивую загрузку и предварительный просмотр изображений в низком качестве.
Для отложенной загрузки есть ряд методов и плагинов. Я рекомендую lazysizes [235] Александра Фаркаса из-за его достойной производительности, функциональности, дополнительной интеграции с Intersection Observer [236] и поддержки плагинов.
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 — не единственный вариант. Есть и другие библиотеки:
Отложенная загрузка — распространённый способ экономии трафика, снижения затрат и улучшения взаимодействия с пользователем. Оцените, насколько она полезна в вашем случае. Для дополнительной информации см. статьи «Ленивая загрузка изображений» [241] и «Реализация прогрессивной загрузки в Medium» [228].
Старые решения для отзывчивых изображений ошибочно обрабатывали запросы изображений при установке свойства 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 показывает, что такие «спрятанные» изображения всё равно загружаются. На самом деле это корректное поведение браузера согласно спецификации встроенных ресурсов.
<div style="display:none"><img src="img.jpg"></div>
Нет. Указанное изображение всё равно будет запрошено. Здесь библиотека не может полагаться на display:none, потому что запрос отправляется раньше, чем JavaScript изменит src.
<div style="display:none">
<div style="background: url(img.jpg)"></div>
</div>
Утвердительный ответ. Фон CSS не извлекается при разборе элемента. Расчёт стилей CSS для дочерних элементов с display:none
менее полезен, так как они не влияют на рендеринг документа. Фоновые изображения дочерних элементов не рассчитываются и не загружаются.
У Джейка Арчибальда есть отличный квест-викторина [242] по ловушкам display:none
. Если сомневаетесь, как конкретный браузер обрабатывает запросы изображений, откройте DevTools и проверьте сами.
Опять же, где возможно используйте <picture> и <img srcset> вместо того, чтобы полагаться на <display:none>.
Время, потраченное на чтение статей для настройки своего конвейера обработки изображений и его последующей доработки зачастую намного дороже, чем плата за эту услугу. Cloudinary [243] предлагает бесплатный сервис, Imgix [244] даёт бесплатную пробную версию, есть свободная альтернатива Thumbor [11], так что вариантов немало.
Для самой быстрой загрузки страницы нужно оптимизировать загрузку изображений, включая выдачу отзывчивых изображений со сжатием на стороне сервера, автоматический выбор оптимального формата и изменение размера. Важно отдавать изображение правильного размера на правильное устройство в правильном разрешении — и как можно быстрее. Сделать это не так просто, как кажется.
Манипуляции с изображениями — специфическая тема. Тут всё постоянно меняется, поэтому начнём с цитаты опытного специалиста, а затем продолжим.
«Если ваш продукт сам по себе не связан с обработкой изображений, то не делайте это самостоятельно. Сервисы вроде Cloudinary [или Imgix, прим. авт.] справятся намного лучше и эффективнее. И если вы беспокоитесь о цене, подумайте, во сколько обойдутся разработка и обслуживание, а также
На данный момент мы склонны согласиться, что лучше использовать CDN для обработки изображений. Рассмотрим два таких сервиса — как они соответствуют списку упомянутых задач.
Cloudinary [243] и Imgix [244] — хорошо известные CDN для обработки изображений. Их используют сотни тысяч разработчиков и компаний по всему миру, включая Netflix и Red Bull.
Первое огромное преимущество CDN перед собственным решением — то, что они используют распределённую глобальную сетевую систему, чтобы хранить ваши изображения ближе к вашим пользователям. И с CDN вам гораздо проще гарантировать актуальность сервиса с будущими изменениями технологий, поскольку не каждый сможет самостоятельно отслеживать тенденции, вносить изменения — это требует обслуживания, отслеживания поддержки браузерами новых форматов и погружения в жизнь сообщества, которое занимается сжатием изображений.
Второе: у каждого сервиса многоуровневую тарифный план: У Cloudinary бесплатный тариф [9], у Imgix недорогой стартовый план. Imgix предлагает бесплатную пробную версию [246], это почти то же самое, что и бесплатный тариф.
Третье: у обоих сервисов есть API. Разработчики могут программно подключаться к CDN и автоматизировать процесс. Доступны клиентские библиотеки, плагины для фреймворков и документация по API, хотя некоторые опции доступны только на дорогих тарифах.
Ограничим дискуссию статичными изображениями. Cloudinary и Imgix предлагают широкий спектр методов обработки изображений. В стандартных и бесплатных тарифах оба поддерживают базовые функции: сжатие, изменение размера, обрезка, генерация уменьшенных копий.
Cloudinary Media Library: По умолчанию Cloudinary выдаёт обычные, а не прогрессивные JPEG [16]. Чтобы активировать эту опцию, поставьте соответствующий значок в «Дополнительных параметрах» или используйте флаг fl_progressive
Cloudinary называет семь широких категорий преобразования [247], в общей сложности 48 подкатегорий. У Imgix более 100 операций обработки изображений [248].
Cloudinary по умолчанию выполняет следующие оптимизации:
Imgix по умолчанию не запускает такие оптимизации, как Cloudinary, но позволяет установить дефолтное качество. В Imgix автоматические параметры помогают автоматизировать базовый уровень оптимизации в каталоге изображений.
В настоящее время используется четыре метода [250]:
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 в основном зависит от задержки [251] и скорости.
Задержка всегда немного больше для полностью некэшированных изображений. Но как только картинка попадает в кэш и расходится по серверам в сети, глобальный CDN находит самый близкий маршрут к пользователю. Вместе с экономией на размере файлов это почти всегда устраняет проблемы с задержкой по сравнению с неоптимизированными изображениями или одиночными серверами, которые пытаются обслужить всю планету.
У обоих CDN широкое покрытие и быстрые серверы, за счёт чего снижается задержка и увеличивается скорость загрузки. Скорость влияет на время загрузки страницы, а это одна из самых важных метрик для пользователей и конверсии.
У Cloudinary около 160 000 клиентов [252], включая Netflix, eBay и Dropbox. Imgix не сообщает количество пользователей, но оно меньше, чем у Cloudinary. Тем не менее, база Imgix включает в себя таких тяжеловесов как Kickstarter, Exposure, unsplash и Eventbrite.
В обработке изображений столько параметров не поддаются объективной оценке, что затруднительно сравнить производительность двух служб. Многое зависит от того, как вы хотите обработать изображение (это займёт разное время), какой размер и разрешение нужны в итоге. В конце концов, самым важным фактором для вас может оказаться стоимость.
CDN стоят денег. Тяжёлый сайт с большим трафиком может платить сотни долларов в месяц на CDN. Необходим определённый уровень знаний и навыков программирования, чтобы получить максимальную отдачу от этих услуг. Но если вы не делаете ничего необычного, то особых проблем не возникнет.
Если вы сейчас отдаёте изображения с собственного сервера или планируете так поступить, возможно, вам следует подумать о CDN.
Ресурсы могут задавать правила кэширования через HTTP-заголовки кэша [253]. В частности, Cache-Control
определяет, кто и как долго должен кэшировать ответы.
Большинство изображений — статические ресурсы, которые не изменятся [254] в будущем. Наилучшая стратегия для них — агрессивное кэширование.
При настройке HTTP-заголовков кэширования, установите Cache-Control со сроком max-age
на год (например, Cache-Control:public; max-age=31536000
). Такое агрессивное кэширование хорошо работает для большинства изображений, особенно для долгоживущих, таких как аватары и картинки в заголовках страниц.
Примечание: если вы отдаёте изображения с помощью PHP, то кэширование отключится из-за дефолтной настройки session_cache_limiter [255]. Проблему можно обойти [256] с помощью
session_cache_limiter('public')
, указавpublic
иmax-age=
. Как вариант, отключение опции и настройка кастомных заголовков управления кэшем.
Критические ресурсы можно предварительно загрузить с помощью <link rel=preload> [257].
<link rel=preload>
— это декларативная загрузка, которая заставляет браузер отправить запрос на ресурс, не блокируя событие onload
для документа. Это повышает приоритет запросов на ресурсы, которые в противном случае будут обнаружены только позже во время парсинга.
Для предварительной загрузки изображений значение as
указывается как image
:
<link rel="preload" as="image" href="logo.jpg"/>
Таким способом оптимизируется загрузка ресурсов для <img>
, <picture>
, srcset
и SVG.
Примечание:
<link rel=preload>
поддерживается [258] в Chrome и браузерах на движке Blink, таких как Opera и Safari Tech Preview [259], а также реализована [260] в Firefox.
Такие сайты, как Philips [261], Flipkart [262] и Xerox [263], используют <link rel=preload>
для предварительной загрузки своих логотипов (часто используемых в начале документа). Kayak [264] тоже применяет предварительную загрузку, чтобы главная картинка в заголовке загружалось максимально быстро.
Предзагрузка ссылки задаётся тегом HTML или в заголовке HTTP Link Header [265]. В любом случае ссылка указывает браузеру начать загрузку ресурса в кэш памяти, потому что страница с высокой степенью вероятности ожидает этот ресурс и нельзя ждать, пока сканер предварительной загрузки или синтаксический анализатор его обнаружит.
Заголовок для изображений будет выглядеть следующим образом:
Link: <https://example.com/logo-hires.jpg>; rel=preload; as=image
Когда Financial Times представила такой заголовок на своём сайте, пользователи стали открывать контент на 1 секунду быстрее [266]:
Снизу: с <link rel=preload>, сверху: без. Сравнение для Moto G4 на канале 3G по тесту WebPageTest до [267] и после [268] оптимизации
Аналогичным образом и Википедия ускорила загрузку «до логотипа», как описывается в их исследовании [269].
Нужно быть уверенным, что предварительная загрузка именно этого ресурса абсолютно необходима, потому что он сдвигает остальной контент в конец очереди. Может быть следует сосредоточить усилия на другом контенте?
Важно избегать rel=preload
для предварительной загрузки изображений без широкой поддержки в браузерах (например, WebP) и избегать применения в отзывчивых изображениях, определённых в srcset, где источник картинки зависит от типа устройства.
Для дополнительной информации ознакомьтесь со статьями «Предзагрузка и приоритеты в Chrome» [270] и «Предварительная загрузка: для чего она хорошо подходит?» [271]
Бюджет производительности — это максимальный лимит, который разработчики стараются не превышать. Например, «не больше 200 КБ картинок на одной странице» или «пользовательский интерфейс должен загружаться быстрее, чем за 3 секунды». Когда бюджет не выполняется — изучите, почему это происходит и как исправить ситуацию.
Бюджеты помогают обсуждать результаты работы. Когда дизайн или бизнес-решение влияет на производительность, сверяйтесь с бюджетом. Если изменение не вписывается в бюджет, это основание для того, чтобы отложить или пересмотреть его.
Я обнаружил, что бюджет производительности выполняется лучше всего, если мониторинг автоматизирован. Вместо изучения сетевых графиков вручную запускается сервис, который автоматически сигнализирует о превышении бюджета. Два таких полезных сервиса — Calibre [272] и SpeedCurve [273].
Как только определён бюджет по размеру изображений, SpeedCurve начинает мониторинг и предупреждает о превышении:
Calibre предлагает установку бюджета для каждого класса устройств. Это полезно, поскольку бюджет по размеру картинок для десктопного ПК по WiFi может сильно отличаться от бюджета для мобильников.
В конечном счёте выбор стратегии оптимизации изображений сводится к типам изображений, которые вы отдаёте пользователям, и разумному набору критериев оценки на выбор. Это может быть SSIM или Butteraugli, а на маленьком наборе иллюстраций можно довериться собственному глазу: что выглядит лучше, а что хуже.
Если вы не можете отдавать изображения в разных форматах, в зависимости от поддержки в браузере:
q=90
слишком расточительно. Для обычных картинок достаточно q=80
, а для DPR 2× даже q=50
. Поскольку Guetzli не выходит на такой низкий уровень, то для веба можно использовать MozJPEG.Если вы можете отдавать изображения в разных форматах, в зависимости от поддержки в браузере, используя <picture>, заголовок Accept [274] или Picturefill [275]:
-m 4 -q 75
хороши для большинства случаев как оптимальное соотношение скорости и степени сжатия.-m 6 -q 100
), который уменьшает файлы, изучив все сочетания параметров. Это на порядок медленнее, но стоит того для статических ресурсов.Удачной компрессии!
Примечание: для более практических советов по оптимизации изображений настоятельно рекомендую книгу Web Performance in Action [276] Джереми Вагнера. В книге High Performance Images [277] тоже много отличных советов и нюансов.
Автор: m1rko
Источник [285]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/obrabotka-izobrazhenij/291725
Ссылки в тексте:
[1] imagemin: https://github.com/imagemin/imagemin
[2] libvips: https://github.com/jcupitt/libvips
[3] Akamai: https://www.akamai.com/us/en/solutions/why-akamai/image-management.jsp
[4] Cloudinary: https://cloudinary.com
[5] imgix: https://imgix.com
[6] Fastly Image Optimizer: https://www.fastly.com/io/
[7] Instart Logic SmartVision: https://www.instartlogic.com/technology/machine-learning/smartvision
[8] ImageOptim API: https://imageoptim.com/api
[9] бесплатный: http://cloudinary.com/pricing
[10] Imageflow: https://github.com/imazen/imageflow
[11] Thumbor: https://github.com/thumbor/thumbor
[12] хостинге: https://www.reg.ru/?rlink=reflink-717
[13] ImageOptim: https://imageoptim.com/
[14] версии: https://imageoptim.com/versions.html
[15] MozJPEG: https://github.com/mozilla/mozjpeg
[16] Progressive JPEG: http://cloudinary.com/blog/progressive_jpegs_and_green_martians
[17] pngquant: https://pngquant.org/
[18] SVGO: https://github.com/svg/svgo
[19] H.264: https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC
[20] WebM: https://www.webmproject.org/
[21] Giflossy: https://github.com/pornel/giflossy
[22] Guetzli: https://research.googleblog.com/2017/03/announcing-guetzli-new-open-source-jpeg.html
[23] WebP: https://developers.google.com/speed/webp/
[24] client-hints: https://developers.google.com/web/updates/2015/09/automating-resource-selection-with-client-hints
[25] Save-Data: https://developers.google.com/web/updates/2016/02/save-data
[26] Введение: #01
[27] Как узнать, нужно ли оптимизировать изображения?: #02
[28] Как выбрать формат?: #03
[29] Скромный JPEG: #04
[30] Режимы сжатия JPEG: #05
[31] Преимущества прогрессивных JPEG: #06
[32] Кто использует прогрессивный JPEG в продакшне?: #07
[33] Недостатки прогрессивного JPEG: #08
[34] Как кодировать файлы в формате прогрессивного JPEG?: #09
[35] Цветовая субдискретизация: #10
[36] Улучшенный JPEG: #11
[37] JPEG-оптимизаторы: #12
[38] Что такое MozJPEG?: #13
[39] Что такое Guetzli?: #14
[40] Сравнение MozJPEG с Guetzli?: #15
[41] Butteraugli: #16
[42] Что такое WebP?: #17
[43] Как работает WebP?: #18
[44] Кто использует WebP в продакшне?: #19
[45] как работает кодирование WebP?: #20
[46] Поддержка браузерами WebP: #21
[47] Как конвертировать изображения в WebP?: #22
[48] Как просмотреть изображения WebP на моей ОС?: #23
[49] Как отдавать WebP?: #24
[50] Оптимизация SVG: #25
[51] Избегайте пережатия графики с потерей качества: #26
[52] Сокращение ненужных расходов на декодирование и изменение размера: #27
[53] Доставка изображений HiDPI с помощью srcset: #28
[54] Художественное преобразование: #29
[55] Управление цветом: #30
[56] Спрайты: #31
[57] Ленивая загрузка некритических изображений: #32
[58] Как избежать ловушки display:none: #33
[59] Есть ли смысл пользоваться CDN для обработки изображений?: #34
[60] Кэширование изображений: #35
[61] Предварительная загрузка важных ресурсов: #36
[62] Бюджеты веб-производительности для изображений: #37
[63] Заключительные рекомендации: #38
[64] Мелочи: #39
[65] HTTP Archive: http://httparchive.org/
[66] доказал: https://calendar.perfplanet.com/2014/images-are-king-an-image-optimization-checklist-for-everyone-in-your-organization/
[67] Исследование Soasta/Google: https://www.thinkwithgoogle.com/marketing-resources/experience-design/mobile-page-speed-load-time/
[68] HTTP Archive: http://jsfiddle.net/rviscomi/rzneberp/embedded/result/
[69] плагин ImageOptim для Sketch: https://github.com/ImageOptim/Sketch-plugin
[70] WebPageTest.org: https://www.webpagetest.org/
[71] Lighthouse: https://developers.google.com/web/tools/lighthouse/
[72] панели аудита: https://developers.google.com/web/updates/2017/05/devtools-release-notes#lighthouse
[73] PageSpeed Insights: https://developers.google.com/speed/pagespeed/insights/
[74] Website Speed Test: https://webspeedtest.cloudinary.com/
[75] руководстве по оптимизации изображений: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/image-optimization
[76] Растровая графика: https://en.wikipedia.org/wiki/Raster_graphics
[77] Векторная графика: https://en.wikipedia.org/wiki/Vector_graphics
[78] осветил компромиссы: http://jlwagner.net/talks/these-images/#/2/2
[79] JPEG: https://en.wikipedia.org/wiki/JPEG
[80] 45% изображений: http://httparchive.org/interesting.php
[81] интерактивный инструмент: http://www.patrickmeenan.com/progressive/view.php?img=https%3A%2F%2Fwww.nps.gov%2Fplanyourvisit%2Fimages%2FGrandCanyonSunset_960w.jpg
[82] удаления EXIF-заголовков: http://www.verexif.com/en/
[83] таблиц Хаффмана: https://en.wikipedia.org/wiki/Huffman_coding
[84] jpegtran: http://jpegclub.org/jpegtran/
[85] jpegrescan: https://github.com/kud/jpegrescan
[86] jpegoptim: https://github.com/tjko/jpegoptim
[87] Facebook перешёл на PJPEG (для своего приложения iOS): https://code.facebook.com/posts/857662304298232/faster-photos-in-facebook-for-ios/
[88] libjpeg-turbo: http://libjpeg-turbo.virtualgl.org/
[89] дискретного косинусного преобразования: https://en.wikipedia.org/wiki/Discrete_cosine_transform
[90] Twitter.com выдаёт прогрессивные JPEG: https://www.webpagetest.org/performance_optimization.php?test=170717_NQ_1K9P&run=2#compress_images
[91] Yelp перешёл на прогрессивный JPEG: https://engineeringblog.yelp.com/2017/06/making-photos-smaller.html
[92] Pinterest: https://pinterest.com/
[93] ImageMagick: https://www.imagemagick.org/
[94] libjpeg: http://libjpeg.sourceforge.net/
[95] jpeg-recompress: https://github.com/danielgtaylor/jpeg-archive
[96] Цветовая субдискретизация: https://en.wikipedia.org/wiki/Chroma_subsampling
[97] до 15−17%: https://calendar.perfplanet.com/2015/why-arent-your-images-using-chroma-subsampling/
[98] «JPEG для крабов»: http://frdx.free.fr/JPEG_for_the_horseshoe_crabs.pdf
[99] «Изучение JPEG»: http://compress-or-die.com/Understanding-JPG/
[100] YCbCr: https://en.wikipedia.org/wiki/YCbCr
[101] RGB: https://en.wikipedia.org/wiki/RGB_color_model
[102] SSIM: https://en.wikipedia.org/wiki/Structural_similarity
[103] Butteraugli: https://github.com/google/butteraugli
[104] JPEG 2000: https://en.wikipedia.org/wiki/JPEG_2000
[105] JPEG XR: https://en.wikipedia.org/wiki/JPEG_XR
[106] HDR: http://wikivisually.com/wiki/High_dynamic_range_imaging
[107] гаммы: http://wikivisually.com/wiki/Gamut
[108] WebP: https://en.wikipedia.org/wiki/WebP
[109] FLIF: https://en.wikipedia.org/wiki/Free_Lossless_Image_Format
[110] JS-декодер: https://github.com/UprootLabs/poly-flif
[111] BPG: https://en.wikipedia.org/wiki/Better_Portable_Graphics
[112] High Efficiency Video Coding: http://wikivisually.com/wiki/High_Efficiency_Video_Coding
[113] JS-декодер: https://bellard.org/bpg/
[114] HEIF: https://en.wikipedia.org/wiki/High_Efficiency_Image_File_Format
[115] WWDC: https://www.cnet.com/news/apple-ios-boosts-heif-photos-over-jpeg-wwdc/
[116] один: https://people.xiph.org/~xiphmont/demo/daala/update1-tool2b.shtml
[117] этих: http://xooyoozoo.github.io/yolo-octo-bugfixes/#cologne-cathedral&jpg=s&webp=s
[118] указать content-type: https://www.igvita.com/2012/12/18/deploying-new-image-formats-on-the-web/
[119] заявлению: https://research.mozilla.org/2014/03/05/introducing-the-mozjpeg-project/
[120] треллис-квантование: https://en.wikipedia.org/wiki/Trellis_quantization
[121] шаблонов таблиц квантования: https://calendar.perfplanet.com/2014/mozjpeg-3-0/
[122] ImageOptim: https://github.com/ImageOptim/ImageOptim/issues/45
[123] плагин imagemin: https://github.com/imagemin/imagemin-mozjpeg
[124] jpeg-compress: https://github.com/imagemin/imagemin-jpeg-recompress
[125] медленнее базового JPEG: http://www.libjpeg-turbo.org/About/Mozjpeg
[126] такой: https://twitter.com/malchata/status/884836650563579904
[127] Guetzli: https://github.com/google/guetzli
[128] хороший тред: https://github.com/google/guetzli/issues/50
[129] сравнение: https://cloudinary.com/blog/a_closer_look_at_guetzli
[130] неверным: https://kornel.ski/faircomparison
[131] говорит: https://github.com/google/guetzli/issues/10#issuecomment-276295265
[132] img-ssim: https://www.npmjs.com/package/img-ssim
[133] Арии Хидаята: https://ariya.io/2017/03/squeezing-jpeg-images-with-guetzli
[134] 25−34%: https://developers.google.com/speed/webp/docs/webp_study
[135] Файлы WebP со сжатием без потерь на 26% меньше файлов PNG: https://developers.google.com/speed/webp/docs/webp_lossless_alpha_study
[136] поддержку WebP: http://caniuse.com/#search=webp
[137] на 1−3 секунды уменьшил время загрузки страниц: https://product.voxmedia.com/2015/8/13/9143805/performance-update-2-electric-boogaloo
[138] 500px: https://iso.500px.com/500px-color-profiles-file-formats-and-you/
[139] статье: https://medium.com/@duhroach/how-webp-works-lossly-mode-33bd2b1d0670
[140] арифметического сжатия: https://www.youtube.com/watch?v=FdMoL3PzmSA&index=7&list=PLOU2XLYxmsIJGErt5rrCqaSGTMyyqNt2H
[141] «Методы сжатия WebP»: https://developers.google.com/speed/webp/docs/compression
[142] данным CanIUse.com: http://caniuse.com/webp
[143] XnConvert: http://www.xnview.com/en/xnconvert/
[144] imagemin-webp: https://github.com/imagemin/imagemin-webp
[145] Плагин WebP для Gulp: https://github.com/sindresorhus/gulp-webp
[146] загрузчик WebP для WebPack: https://www.npmjs.com/package/webp-loader
[147] cwebp: https://developers.google.com/speed/webp/docs/cwebp
[148] оптимизации изображений в Bash: https://jeremywagner.me/blog/bulk-image-optimization-in-bash
[149] распараллеливании: https://jeremywagner.me/blog/faster-bulk-image-optimization-in-bash
[150] «Создание изображений WebP с помощью Android Studio»: https://developer.android.com/studio/write/convert-webp.html
[151] Facebook экспериментировал с WebP: https://www.cnet.com/news/facebook-tries-googles-webp-image-format-users-squawk/
[152] плагин Quick Look для WebP: https://github.com/Nyx0uf/qlImageSize
[153] пакет кодеков WebP: https://storage.googleapis.com/downloads.webmproject.org/releases/webp/WebpCodecSetup.exe
[154] сигнализировать о поддержке WebP: http://vincentorback.se/blog/using-webp-images-with-htaccess/
[155] заголовок Accept: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept
[156] образец htaccess: https://github.com/vincentorback/WebP-images-with-htaccess
[157] скриптов конфигурации для выдачи WebP: https://github.com/igrigorik/webp-detect
[158] когда это возможно: http://cloudinary.com/documentation/responsive_images#automating_responsive_images_with_client_hints
[159] Photon: https://jetpack.com/support/photon/
[160] Cache Enabler: https://wordpress.org/plugins/cache-enabler/
[161] спецификация GIF89a: https://www.w3.org/Graphics/GIF/spec-gif89a.txt
[162] Количество цветов, количество кадров и пропорции: http://gifbrewery.tumblr.com/post/39564982268/can-you-recommend-a-good-length-of-clip-to-keep-gifs
[163] анимированные GIF в Twitter на самом деле не являются GIF-файлами: http://mashable.com/2014/06/20/twitter-gifs-mp4/#fiiFE85eQZqW
[164] Imgur при загрузке конвертирует GIF в MP4: https://thenextweb.com/insider/2014/10/09/imgur-begins-converting-gif-uploads-mp4-videos-new-gifv-format/
[165] ffmpeg: https://www.ffmpeg.org/
[166] Rigor: http://rigor.com/blog/2015/12/optimizing-animated-gifs-with-html5-video
[167] Gifify: https://github.com/vvo/gifify
[168] «Книгу GIF»: https://rigor.com/wp-content/uploads/2017/03/TheBookofGIFPDF.pdf
[169] SVGOMG: https://jakearchibald.github.io/svgomg/
[170] simplify: http://jlwagner.net/talks/these-images/#/2/10
[171] плагин Sketch для SVGO: https://www.sketchapp.com/extensions/plugins/svgo-compressor/
[172] установить как CLI: https://www.npmjs.com/package/svgo
[173] зазиповать файлы SVG: https://calendar.perfplanet.com/2014/tips-for-optimising-svg-delivery-for-the-web/
[174] минимальная: https://twitter.com/addyosmani/status/638753485555671040
[175] много продвинутых трюков: https://www.clicktorelease.com/blog/svg-google-logo-in-305-bytes/
[176] отлично подходит: https://css-tricks.com/icon-fonts-vs-svg/
[177] поддерживается в браузерах: http://www.sitepoint.com/tips-accessible-svg/
[178] svg-sprite: https://github.com/jkphl/svg-sprite
[179] IcoMoon: https://icomoon.io/
[180] CSS Sprite: https://css-tricks.com/css-sprites/
[181] Symbol Sprite: https://css-tricks.com/svg-use-with-external-reference-take-2
[182] Stacked Sprite: http://simurai.com/blog/2012/04/02/svg-stacks
[183] практичные советы: https://una.im/svg-icons/#%F0%9F%92%81
[184] переход от шрифтов для иконок к SVG: https://www.sarasoueidan.com/blog/icon-fonts-to-svg/
[185] «Практическая книга по SVG»: https://abookapart.com/products/practical-svg
[186] часть 1: https://medium.com/larsenwork-andreas-larsen/optimising-svgs-for-web-use-part-1-67e8f2d4035
[187] часть 2: https://medium.com/larsenwork-andreas-larsen/optimising-svgs-for-web-use-part-2-6711cc15df46
[188] «Подготовка и экспорт значков SVG в Sketch»: https://medium.com/sketch-app-sources/preparing-and-exporting-svg-icons-in-sketch-1a3d65b239bb
[189] отличного видео: https://www.youtube.com/watch?v=w7vXJbLhTyI
[190] сопроводительной статьи: http://cloudinary.com/blog/why_jpeg_is_like_a_photocopier
[191] srcset/sizes
: https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images
[192] временной шкале: https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/performance-reference
[193] мобильной версии: https://medium.com/@paularmstrong/twitter-lite-and-high-performance-react-progressive-web-apps-at-scale-d28a00e780a3
[194] Соотношение пикселей устройства: https://stackoverflow.com/a/21413366
[195] material.io: https://material.io/devices/
[196] mydevice.io: https://mydevice.io/devices/
[197] Cloudinary: http://cloudinary.com/blog/how_to_automatically_adapt_website_images_to_retina_and_hidpi_devices
[198] Imgix: https://docs.imgix.com/apis/url/dpr
[199] бесплатном курсе Udacity: https://www.udacity.com/course/responsive-images--ud882
[200] руководстве по изображениям: https://developers.google.com/web/fundamentals/design-and-ui/responsive/images
[201] Client Hints: https://www.smashingmagazine.com/2016/01/leaner-responsive-images-client-hints/
[202] художественное преобразование: http://usecases.responsiveimages.org/#art-direction
[203] Cloudinary: http://cloudinary.com/blog/automatically_art_directed_responsive_images%20
[204] пример: https://ericportis.com/etc/cloudinary/
[205] феномен восприятия: http://hubel.med.harvard.edu/book/ch8.pdf
[206] Цветовые модели: https://en.wikipedia.org/wiki/Gamma_correction
[207] «Понятие цветовых моделей и систем цвета»: https://www.designersinsights.com/designer-resources/understanding-color-models/
[208] Цветовые пространства: http://www.dpbestflow.org/color/color-space-and-color-profiles#space
[209] sRGB: https://en.wikipedia.org/wiki/SRGB
[210] стандарт: https://www.w3.org/Graphics/Color/sRGB.html
[211] Adobe RGB: https://en.wikipedia.org/wiki/Adobe_RGB_color_space
[212] ProPhoto RGB: https://en.wikipedia.org/wiki/ProPhoto_RGB_color_space
[213] Yardstick: https://yardstick.pictures/tags/img%3Adci-p3
[214] гамма-кривой: http://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/
[215] примерно на 50% шире: http://www.petrvodnakphotography.com/Articles/ColorSpace.htm
[216] Clipping Path: http://clippingpathzone.com/blog/essential-photoshop-color-settings-for-photographers
[217] Широкая гамма: http://www.astramael.com/
[218] Международного цветового консорциума: http://www.color.org/icc_specs2.xalter
[219] Nine Degrees Below: https://ninedegreesbelow.com/photography/articles.html
[220] Color Correct Rendering: https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/ptuKdRQwPAo
[221] «Справочник нерда по цвету в интернете»: https://css-tricks.com/nerds-guide-color-web/
[222] спрайтов изображений: https://developers.google.com/web/fundamentals/design-and-ui/responsive/images#use_image_sprites
[223] HTTP/2: https://hpbn.co/http2/
[224] загружать картинки по отдельности: https://deliciousbrains.com/performance-best-practices-http2/
[225] такое обсуждалось: https://discourse.wicg.io/t/a-standard-way-to-lazy-load-images/1153/10
[226] Medium: https://medium.com/
[227] Pinterest: https://www.pinterest.com/
[228] CSS-фильтров: https://jmperezperez.com/medium-image-progressive-loading-placeholder/
[229] разными графическими форматами: https://jmperezperez.com/webp-placeholder-images/
[230] подход: https://code.facebook.com/posts/991252547593574/the-technology-behind-preview-photos/
[231] LQIP loader: https://lqip-loader.firebaseapp.com/
[232] SQIP: https://github.com/technopagan/sqip
[233] Primitive: https://github.com/fogleman/primitive
[234] можно комбинировать: https://calendar.perfplanet.com/2017/progressive-image-loading-using-intersection-observer-and-sqip/
[235] lazysizes: https://github.com/aFarkas/lazysizes
[236] Intersection Observer: https://developers.google.com/web/updates/2016/04/intersectionobserver
[237] Lazy Load XT: http://ressio.github.io/lazy-load-xt/
[238] BLazy.js: https://github.com/dinbror/blazy
[239] Unveil: http://luis-almeida.github.io/unveil/
[240] yall.js (Yet Another Lazy Loader): https://github.com/malchata/yall.js
[241] «Ленивая загрузка изображений»: https://jmperezperez.com/lazy-loading-images/
[242] квест-викторина: https://jakearchibald.github.io/request-quest/
[243] Cloudinary: http://cloudinary.com/
[244] Imgix: https://www.imgix.com/
[245] Крис Гмыр: https://medium.com/@cmgmyr/moving-from-self-hosted-image-service-to-cloudinary-bd7370317a0d
[246] пробную версию: https://www.imgix.com/pricing
[247] семь широких категорий преобразования: http://cloudinary.com/documentation/image_transformations
[248] 100 операций обработки изображений: https://docs.imgix.com/apis/url?_ga=2.52377449.1538976134.1501179780-2118608066.1501179780
[249] Кодирование в JPEG с помощью MozJPEG: https://twitter.com/etportis/status/891529495336722432
[250] четыре метода: https://docs.imgix.com/apis/url/auto
[251] задержки: https://docs.google.com/a/chromium.org/viewer?a=v&pid=sites&srcid=Y2hyb21pdW0ub3JnfGRldnxneDoxMzcyOWI1N2I4YzI3NzE2
[252] 160 000 клиентов: http://cloudinary.com/customers
[253] HTTP-заголовки кэша: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#cache-control
[254] не изменятся: http://kean.github.io/post/image-caching
[255] session_cache_limiter: http://php.net/manual/en/function.session-cache-limiter.php
[256] обойти: https://stackoverflow.com/a/3905468
[257] <link rel=preload>: https://www.w3.org/TR/preload/
[258] поддерживается: http://caniuse.com/#search=preload
[259] Safari Tech Preview: https://developer.apple.com/safari/technology-preview/release-notes/
[260] реализована: https://bugzilla.mozilla.org/show_bug.cgi?id=1222633
[261] Philips: https://www.usa.philips.com/
[262] Flipkart: https://www.flipkart.com/
[263] Xerox: https://www.xerox.com/
[264] Kayak: https://kayak.com/
[265] заголовке HTTP Link Header: https://www.w3.org/wiki/LinkHeader
[266] на 1 секунду быстрее: https://twitter.com/wheresrhys/status/843252599902167040
[267] до: https://www.webpagetest.org/result/170319_Z2_GFR/
[268] после: https://www.webpagetest.org/result/170319_R8_G4Q/
[269] исследовании: https://phabricator.wikimedia.org/phame/post/view/19/improving_time-to-logo_performance_with_preload_links/
[270] «Предзагрузка и приоритеты в Chrome»: https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf
[271] «Предварительная загрузка: для чего она хорошо подходит?»: https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/
[272] Calibre: https://calibreapp.com/docs/metrics/budgets
[273] SpeedCurve: https://speedcurve.com/blog/tag/performance-budgets/
[274] заголовок Accept: https://www.igvita.com/2013/05/01/deploying-webp-via-accept-content-negotiation/
[275] Picturefill: https://scottjehl.github.io/picturefill/
[276] Web Performance in Action: https://www.manning.com/books/web-performance-in-action
[277] High Performance Images: http://shop.oreilly.com/product/0636920039730.do
[278] JPEG XT: https://jpeg.org/jpegxt/
[279] libjpeg-turbo: https://libjpeg-turbo.org/
[280] PIK: https://github.com/google/pik
[281] Исследование: https://encode.ru/threads/2814-Psychovisual-analysis-on-modern-lossy-image-codecs
[282] ImageMagick: https://www.imagemagick.org/script/index.php
[283] находили: https://imagetragick.com/#moreinfo
[284] img.decode(): https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-decode
[285] Источник: https://habr.com/post/422531/?utm_campaign=422531
Нажмите здесь для печати.