Автоматизация сжатия и кодирования

Сделайте создание высокопроизводительных источников изображений неотъемлемой частью процесса разработки.

Все синтаксисы в этом курсе — от кодирования данных изображения до насыщенной информацией разметки, которая обеспечивает адаптивность изображений — являются методами взаимодействия машин с машинами. Вы обнаружили несколько способов, с помощью которых клиентский браузер сообщает о своих потребностях серверу, а сервер отвечает тем же. Адаптивная разметка изображений (в частности, srcset и sizes ) позволяет описать шокирующий объем информации в относительно небольшом количестве символов. Хорошо это или плохо, но такая краткость задумана: если сделать эти синтаксисы менее краткими и облегчить их анализ разработчикам, это могло бы затруднить их анализ браузером . Чем больше сложности добавляется к строке, тем больше вероятность ошибок синтаксического анализатора или непреднамеренных различий в поведении одного браузера в другом.

Окно автоматического кодирования изображений.

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

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

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

Автоматизация сжатия и кодирования

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

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

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

Что касается самой обработки, существует огромное количество библиотек обработки изображений с открытым исходным кодом, которые предоставляют методы пакетного преобразования, модификации и редактирования изображений, конкурируя по скорости, эффективности и надежности. Эти библиотеки обработки позволят вам применять настройки кодирования и сжатия ко всем каталогам изображений одновременно, без необходимости открывать программное обеспечение для редактирования изображений, и таким образом, чтобы сохранить исходные источники изображений, если эти настройки потребуется изменить на месте. летать. Они предназначены для работы в различных контекстах, от локальной среды разработки до самого веб-сервера. Например, ImageMin для Node.js, ориентированный на сжатие, можно расширить для соответствия конкретным приложениям с помощью набора плагинов , а кроссплатформенный ImageMagick и Sharp на базе Node.js предлагают ошеломляющее количество функций прямо из коробки.

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

Локальные инструменты и рабочие процессы разработки

Обработчики задач и сборщики задач, такие как Grunt, Gulp или Webpack, можно использовать для оптимизации ресурсов изображений наряду с другими распространенными задачами, связанными с производительностью, такими как минимизация CSS и JavaScript. Для иллюстрации давайте возьмем относительно простой пример использования: каталог вашего проекта содержит дюжину фотографических изображений, предназначенных для использования на общедоступном веб-сайте.

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

Хотя это было бы повторяющейся и трудоемкой работой, если бы она выполнялась с помощью программного обеспечения для редактирования изображений, средства запуска задач, такие как Gulp , предназначены для автоматизации именно такого рода повторений. Плагин , реагирующий на gulp , использующий Sharp , является одним из многих вариантов, которые следуют одной и той же схеме: собирают все файлы в исходном каталоге, перекодируют их и сжимают на основе одного и того же стандартизированного обозначения «качества». вы узнали в разделе «Форматы изображений и сжатие» . Полученные файлы затем выводятся по заданному вами пути, готовые к использованию в атрибутах src ваших элементов img , обращенных к пользователю, при этом исходные файлы остаются нетронутыми.

const { src, dest } = require('gulp');
const respimg = require('gulp-responsive');

exports.webp = function() {
  return src('./src-img/*')
    .pipe(respimg({
      '*': [{
        quality: 70,
        format: ['webp', 'jpeg'],
        progressive: true
      }]
  }))
  .pipe(dest('./img/'));
}

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

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

const { src, dest } = require('gulp');
const respimg = require('gulp-responsive');

exports.default = function() {
  return src('./src-img/*')
    .pipe(respimg({
    '*': [{
            width: 1000,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-1000' }
            },
            {
            width: 800,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-800' }
            },
            {
            width: 400,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-400' },
        }]
        })
    )
    .pipe(dest('./img/'));
}

В приведенном выше примере исходное изображение (monarch.png) имело размер более 3,3 МБ. Самый большой файл, созданный этой задачей (monarch-1000.jpeg), имеет размер примерно 150 КБ. Самый маленький файл, Monarch-400.web, имеет размер всего 32 КБ.

[10:30:54] Starting 'default'...
[10:30:54] gulp-responsive: monarch.png -> monarch-400.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-800.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-1000.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-400.webp
[10:30:54] gulp-responsive: monarch.png -> monarch-800.webp
[10:30:54] gulp-responsive: monarch.png -> monarch-1000.webp
[10:30:54] gulp-responsive: Created 6 images (matched 1 of 1 image)
[10:30:54] Finished 'default' after 374 ms

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

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

Адаптивная разметка изображений на практике

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

srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w"

Помните, что содержимое атрибута srcset носит описательный, а не предписывающий характер. Нет никакого вреда в перегрузке атрибута srcset , если соотношение сторон каждого источника единообразно. Атрибут srcset может содержать URI и ширину каждого альтернативного выреза, сгенерированного сервером, без каких-либо ненужных запросов, и чем больше источников-кандидатов мы предоставим для визуализированного изображения, тем эффективнее браузер сможет адаптировать запросы.

Как вы узнали в разделе «Адаптивные изображения» , вам понадобится использовать элемент <picture> для беспрепятственной обработки резервного шаблона WebP или JPEG. В этом случае вы будете использовать атрибут type совместно с srcset .

<picture>
  <source type="image/webp" srcset="filename-1000.webp 1000w, filename-800.webp 800w, filename-400.webp 400w">
  <img srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w" sizes="…" alt="…">
</picture>

Как вы узнали, браузеры, поддерживающие WebP, распознают содержимое атрибута type и выбирают атрибут srcset этого элемента <source> в качестве списка кандидатов на изображение. Браузеры, которые не распознают image/webp как допустимый тип носителя, будут игнорировать этот <source> и вместо этого использовать атрибут srcset внутреннего элемента <img> .

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

Поскольку масштабирование изображения вниз визуально не вызывает затруднений, а кодирование JPEG поддерживается повсеместно, разумным выбором является самый большой формат JPEG.

<picture>
  <source type="image/webp" srcset="filename-1000.webp 1000w, filename-800.webp 800w, filename-400.webp 400w">
  <img src="filename-1000.jpg" srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w" sizes="…" alt="…">
</picture>

sizes может быть немного сложнее иметь дело. Как вы узнали , sizes обязательно зависят от контекста: вы не можете заполнить атрибут, не зная, сколько места должно занимать изображение в визуализированном макете. Для наиболее эффективных запросов атрибут точных sizes должен присутствовать в нашей разметке в момент, когда эти запросы делаются конечным пользователем, задолго до того, как будут запрошены стили, управляющие макетом страницы. Полное отсутствие sizes является не только нарушением спецификации HTML, но и приводит к поведению по умолчанию, эквивалентному sizes="100vw" — сообщению браузеру о том, что это изображение ограничено только самим окном просмотра, в результате чего выбирается максимально возможный источник-кандидат.

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

Отчет об адаптивных изображениях, показывающий несоответствие размера и ширины.

Инструмент для анализа атрибутов sizes , безусловно, полезен, но он имеет еще большую ценность как инструмент для их массового создания. Как вы знаете, синтаксис srcset и sizes предназначен для визуальной оптимизации запросов к ресурсам изображений. Хотя это и не то, что когда-либо следует использовать в рабочей среде, значение заполнителя sizes по умолчанию, равное 100vw , вполне разумно при работе над макетом страницы в вашей локальной среде разработки. Как только стили макета будут установлены, запуск respImageLint предоставит вам индивидуальные атрибуты sizes , которые вы сможете скопировать и вставить в свою разметку, на уровне детализации, гораздо более высоком, чем тот, который написан вручную:

Отчет об адаптивных изображениях с предлагаемыми размерами.

Хотя запросы изображений, инициированные разметкой, отображаемой на сервере, происходят слишком быстро, чтобы JavaScript мог сгенерировать атрибут sizes на стороне клиента, те же рассуждения не применимы, если эти запросы инициируются на стороне клиента. Например, проект Lazysizes позволяет вам полностью откладывать запросы изображений до тех пор, пока не будет создан макет, позволяя JavaScript генерировать для нас значения наших sizes — огромное удобство для вас и гарантия максимально эффективных запросов для ваших пользователей. . Однако имейте в виду, что этот подход означает принесение в жертву надежности разметки, отображаемой на сервере, и оптимизацию скорости, встроенную в браузеры, а инициирование этих запросов только после того, как страница была отображена, окажет огромное негативное влияние на ваш показатель LCP.

Конечно, если вы уже зависите от клиентской среды рендеринга, такой как React или Vue, вы уже берете на себя этот долг — и в этих случаях использование Lazysizes означает, что ваши атрибуты sizes могут быть почти полностью абстрагированы. А еще лучше: по мере того, как sizes="auto" для ленивых загружаемых изображений получает консенсус и нативные реализации, Lazysizes фактически станет полифилом для этого нового стандартизированного поведения браузера.