Оптимізація графіки для web

  1. Як визначити яке зображення показати
  2. Складність і кількість коду
  3. Автоматизація процесу
  4. від перекладача

Це переклад статті Image Optimization автора Estelle Weyl .

Напевно, кожен веб-розробник знає, що коли мова заходить про продуктивність і зручність ипользования (UX) кожне зображення на сторінці має величезне значення: перші плоди в оптимізації web-сторінок може принести саме робота з зображеннями. Використання методик стиснення зображень без втрат якості дозволяє знизити сумарний розмір сторінки не завдаючи шкоди для користувача досвіду (UX) роботи з такими сторінками, тим самим, покращуючи продуктивність і збільшуючи конверсію. Існує багато методів для визначення того, які саме зображення підтримуються, і вам залишається тільки підготувати "правильні" зображення і віддати їх користувачеві. Створення оптимальних зображень для всіх користувачів на всіх типах пристроїв повинно стати метою всіх розробників (доступність повинна стати ще однією метою, але зараз не про це).

Як визначити яке зображення показати

Існує кілька методик для відображення потрібного зображення, наприклад, медіа запити при використанні фонових зображень, або використання елементів <picture> і <source> спільно з srcset.
Використовуючи CSS @media queries можна відображати різні фонові зображення в залежності від розміру вікна перегляду або щільності пікселів на пристрої користувача.

Наприклад, ви можете показати зображення lowres.jpg для старих ноутбуків і hires.jpeg для iPad Pro:

1
2
3
4
5
6
7
8
9
header {
background-image: url (img / hires_header.jpg);
}

@media only screen and (min-device-pixel-ratio: 2) and (min-width: 1024px) {
header {
background-image: url (img / hires_header.jpg);
}
}

А як бути зі звичайними зображеннями переднього плану?

Методика адаптивних ізораженій ще з 2013 року була заснована на тому, що SVG має свою свобственную ширину і висоту контейнера, і медіавираженія в них відштовхуються від цих розмірів, а не від розмірів вікна браузера (viewport).
На щастя, постійна підтримка браузерами тега <picture> і srcset дозволяють не використовувати вже цей хак.

Основоного проблемою в зображеннях переднього плану є те, що браузер має інформацію про розмір екрану (viewport) і щільності пікселів на екрані, але й гадки не має про розмір завантажуваного зображення і того, як воно співвідноситься з розміром екрану. Але, розробник знає і може вказувати їх.

Подібно медіазапросам за допомогою тегів <picture, <source> і атрибута srcset розробник може диктувати браузеру які зображення відображати для того чи іншого розміру екрану або щільності пікселів.

1
2
3
4
5
6
<Picture>
<Source srcset = "small_lowres.jpg, small_highres.jpg 2x" media = "(max-width: 768px)">
<Source srcset = "default.jpg, default_highres.jpg 2x">
<Source srcset = "large_lowres.jpg, large_highres.jpg 2x" media = "(min-width: 1024px)">
<Img src = "default.jpg" alt = "image descriptor">
</ Picture>

Примітка! Завжди використовуйте за замовчуванням тег <img> всередині кожного <picture>, а також атрибут alt для тега.

Ви можете використовувати просто тег <img> без використання <picture> і в тезі img вказати атрибути srcset з набором ізораженій і sizes для опису області їх застосування.

1
2
3
4
5
6
7
8
<Img src = "default.jpg"
srcset = "large.jpg 1024w,
medium.jpg 768w,
default.jpg 420w "
sizes = "(min-width: 1024px) 1024px,
(Min-width: 768px) 90vw,
100vw "
alt = "image descriptor" />

Ми також можемо відображати різні типи зображень використовуючи атрибут type:

1
2
3
4
5
6
<Picture>
<Source srcset = "photo.jxr" type = "image / vnd.ms-photo">
<Source srcset = "photo.jp2" type = "image / jp2">
<Source srcset = "photo.webp" type = "image / webp">
<Img srcset = "photo.jpg" alt = "My beautiful face">
</ Picture>

Якщо вас дивує код вище, JPEG-XR старий MIME image / vnd.ms-photo для Windows Media Photo, пропріетарний формат зображень від Microsoft, підтримуваний IE8 і вище, включаючи Microsoft Edge. jp2 - це розширення для формату JPEG 2000, який підтримується браузером Safari. WebP - це формат ізоюраженій зі стисненням без втрат якості і підтримується на даний момент браузерами Chrome і Opera. А Firefox буде підтримувати формати графіки, як PNG-A, SVG, GIF і JPEG (як в коді вище).

Chrome - WebP
IE 9 + / Edge - JPEG-XR
Opera - WebP
Safari - JPEG-2000

Для Firefox і IE8 потрібно передбачити запасний варіант у вигляді зображень JPEG або PNG. І хоча Safari і Firefox експериментують з підтримкою WebP зображень, поки немає впевненості в тому, що така підтримка незабаром з'явиться. У будь-якому випадку, можна перевірити підтримку на сайті Can I Use .

Для більш детального вивчення можливостей є хороші онлайн підручники для медіавираженій , тега <picture> і srcset .

Складність і кількість коду

Основний Пролема в такому рішенні (дивись код вище), це велика кількість коду, який необ'одімо написати для того, щоб покрити якомога більше варіантів розмірів екранів і щільності пікселів. Розставити контрольні точки для кожного дозволу безумовно можна, але це складно, і ви навряд чи хотіли б цим займатися вручну. На щастя, для написання таких умов можна і потрібно автоматизувати.

Оптимальним рішенням в тому випадку буде генерація коду на стороні сервера під три з чотирьох основних критеріїв, таких як: розмір вікна (viewport), щільність пікселів, підтримка клієнтом формату зображення і ставлення розміру зображення до розміру екрана. Чому три з чотирьох? Ви завжди можете використовувати всі переваги розуміння браузером sourcesets, але ви не використовуєте всі комбінації, а лише деякі з них.

Якщо ваш DOM формується в браузері тільки на клієнтській стороні за допомогою JavaScript, наприклад, як у React додатків, маючи інформацію про клієнтському пристрої ви можете запросити правильне зображення, але користувачі будуть якийсь час бачити частково завантажений екран (в той час, поки обробляється код на клієнті).

У тому випадку, коли ви не генеруєте весь HTML на стороні клієнта, підміна шляху до зображення теж не буде оптимальним рішенням, так як під час парсинга документа браузер почне завантажувати оригінальне зображення, а потім, коли відпрацює JavaScript, браузер приступить до скачування іншого, більш оптимального для нього, зображення.

І якщо ви є прихильником прогресивного улушенія, ви повинні розуміти, що вихідне зображення буде завантажено в будь-якому випадку після того як HTML документа буде проаналізовано.

На жаль, підказки, які відправляються на сервер з інформацією про щільність пікселів екрану або підтримкою WebP, у вигляді заголовків HTTP запитів були реалізовані тільки в Blink (Chrome і Opera). Коли ви маєте інформацію про дозвіл і розмірі екрану користувача ви можете автоматично віддавати правильні зображення використовуючи прогресивне поліпшення на стороні сервера. За допомогою таких заголовків ми можемо визначити підтримку формату зображення WebP (Chrome і Opera підтримують такі типи заголовків), дозвіл і розмір вікна пристрою клієнта. У Instart Logic у нас є скрипт під назвою Nanovisor, який повторює функціональність HTTP заголовків для браузерів, які не підтримують цю технологію, що дозволяє нам відправляти клієнту оптимізовані зображення.

Ви можете також аналізувати рядок загловка UserAgent разом з деякою додатковою інформацією для того, щоб визначити тип підтримуваних графічних файлів у конкретного користувача. Дізнавшись це, ви можете підмінити розширення файлу або можете віддати зображення потрібного формату але з "неправильним" розширенням. Наприклад, якщо користувач запросив файл foo.jpg ми можемо отдеть йому потрібний тип файлу, під все тим же ім'ям foo.jpg. У Instart Logic ми віддаємо користувачам WebP для Chrome і Opera, і JPEG-XR для Edge без зміни імені файлу, ми просто завжди використовуємо .jpg в кінці імені файлу. Ми користуємося тим фактом, що всі браузери коректно відображають зображення керуючись MIME не звертаючи уваги на розширення файлів. Таким чином, ми можете створювати одну й ту ж саму розмітку html для різних браузерів, а з боку сервера віддавати кажому браузеру потрібне зображення.

Якщо ви збираєтеся генерувати різні формати зображень на основі поддерку браузером, але з одним розширенням файлу, ви повинні забезпечити збереження (кеш) зображень на стороні сервера і якось розділяти зображення з одним ім'ям і різним типом вмісту. Або вам потрібно з боку клієнта слати запити з потрібних разширения файлу. Якщо ви знаєте краще або ще одне рішення, дайте мені знати.

Автоматизація процесу

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

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

Процес оптимізації зображень може займати багато часу, особливо для сайтів з динамічним вмістом, де кількість може обчислюватися тисячами, сотнями тисяч або навіть мільйонами зображень з різними розмірами і типами. І в цьому випадку може допомогти програмне забезпечення, наприклад, ImageMagick. ImageMagick дозволяє конвертувати зображення в різні формати, такі як: PNG, JPEG, JPEG-2000, GIF і навіть WebP. Поддерівается ще безліч форматів і конвертувати зображення можна використовуючи командний рядок:

1
convert myImg.jpg -quality 78 -define webp: lossless = true myImg.webp

Наведена вище команда збереже копію зображення myImg.jpg в форматі WebP, при цьому конвертація буде здійснено без видимих ​​втрат до якості 78%.
Так само, за допомогою ImageMagic ви можете змінити розмір зображення використовуючи прапор -resize

1
convert myImg.jpg -quality 78 -resize 50% myImg.webp

Наведена вище команда створить новий файл у форматі WebP розміром 50% від оригінального зображення (myImg.jpg) і якістю 78%.

За допомогою командного рядка можна автоматично створювати зображення в потрібних вам розмірах і якості. Труднощі може викликати тільки визначення оптимальної якості зображення і ступеня стиснення. І цей крок, можливо, прийдеться виконувати вручну.

Завдання пошуку оптимального якості для кожного зображення буде займати дуже багато часу або вимагати використання великої кількості людей. Тому, більшість інструментів для перетворення зображень зменшують розмір файлу за рахунок погіршення якості зображення, використовуючи загальний коефіцієнт стиснення. Наприклад, коли я оптимізував зображення для свого сайту з декількома картинками, я індивідуально підібрав степере стиснення для них в межах від 35% до 88%. Для галерей та інших проектів з множинами зображень я використовував Adobe Fireworks для автоматизації процесу конвертації і зберігав все зображення з якістю 78%. Більшість програм для автоматизації оптимізації зберігають зображення з якістю близько 80%. Грунтуючись на своєму досвіді я вибираю зазвичай якість 78%. Тим не менше, немає якогось магічесого універсального числа для вибору качетсва зображення.

Рівень стиснення сильно залежить від того, що зображено на картинці і, в цілому, залежить від рівня деталізації. І в залежності від вмісту потрібно виставляти степере стиснення. Чим більш деталізовано зображення, тим нижче повинна бути степере стиснення (в районі 90%), в той час як зображення з меншою кількістю деталізованих ділянок будуть відмінно виглядати навіть при якості нижче 50%.

Не виключається і автоматизована настройка якості зображення. Так, платформа Instart Logic's використовує комп'ютерний зір і машинне навчання для контентно-залежною оптимізації зображень. Зображення оптимізуються з урахуванням розмірів і можливостей браузера, якості інтернет з'єднання і оптимальних коефіцієнтів стиснення зображення без видимих ​​втрат якості. Процес автоматизованої оптимізації якості зображення, то що ми називаємо "SmartVision", будується на основі алгоритмічного підходу і машинного навчання для отримання адаптивних налаштувань для кожного зображення окремо з найкращими поєднаннями якості зображення і його ваги. Вдосконалені алгоритми комп'ютерного зору дозволяють збільшити відсоток стиснення зображення без видимих ​​втрат якості. Parvez Ahammad в своїй статті ще в 2014 році описав ці алгоритми .

За останні 6 років браузери стали працювати швидше, але в той же час, зросла середній час завантаження сайту. І виною тому, в тому числі, розмір зображень. Сучасні засоби дозволяють частково вирішити цю проблему. Тому, хорошим тоном буде, якщо ви станете виділяти час на оптимізацію зображень.

від перекладача

У 2015 році я опублікував статтю webp - вже пора? , В якій описав можливості щодо нового на той момент формату зображення WebP. Через більш ніж півтора року підтримкою формату WebP все ще можуть похвалитися лише Chrome і Opera. Але, використання цього формату на декількох великих проектах в AlterEGO зарекомендувало себе дуже позитивно. Ми знизили споживання трафіку, завантаження каналу і швидкість завантаження сторінок сайту. При цьому, зображення не втратили в якості. А це дуже важливо, наприклад, для інтернет магазинів, де від якості зображення безпосередньо можуть залежати продажу.

Основною проблемою, з якою нам довелося зіткнутися при використанні оптимізованих зображень стала проблема продуктивності. Великий обсяг графічних файлів (фото для товарів) і постійні оновлення фото не дозволяли виконувати прегенерацію. Більш того, використання оптимального розміру зображення (в залежності від щільності пікселів екрану і розмірів viewport) зробило обов'язковим умова генерації зображення "на вимогу". Тобто на льоту. Запропоноване в моїй статті рішення з іспользваніем php і бібліотеки Imagick для зміни розмірів і формату зображень виявилося марним. Час генерації зображення було занадто великим і воно ще більше збільшувалася зі збільшенням кількості запитів. Проблему вдалося вирішити за допомогою модуля PageSpeed для NGINX і організації кешування і збереження згенерованих зображень на диск. Нам вдалося добитися максимального часу генерації зображень в районі 500мс при середньому часу повторної віддачі зображення за 25-30мс. Але, це тема для окремої статті.

Чому три з чотирьох?