Перейти к содержимому

Оптимизация изображений из коробки

Для инте­ре­су­ю­щихся: изоб­ра­жения в 11ty сжимает библио­тека sharp.

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

Пред­ста­вим, что я приложил в эту заметку скан первой стра­ницы газеты The Evening Star от дня сброса атомной бомбы на На­га­саки (оригинал). Я сказал «пред­ста­вим», потому что этот PNG-­файл с раз­ре­ше­нием 5500×8000 пикселей весит 29 Мб и если я действи­тельно его приложу, вес исход­ников Триремы раздует где-то на треть.

Так вот, в этой гипо­те­ти­че­ской ситу­ации вы, как ­чи­та­тель, скачаете не 29 Мб, а от силы 7, если даже не 3. Каче­ство не у­па­дёт, размеры изоб­ра­жения оста­нутся теми же — а ска­ча­ется всё в 4–10 раз быст­рее.

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

Фрагмент в оригинале, 429 Кб
second-atom-bomb-evening-star-front-page_crop_width638
Оптимизированное изображение, 71 Кб

Напомню, что если вы захо­тите умень­шить размеры изоб­ра­же­ния, вы можете сделать это, не вы­ходя из за­ме­точ­ника: строке с изоб­ра­же­нием ! [alt text] (image.jpеg) добавьте |желанная_ширина_в_пикселях справа от альт-­текста — должно полу­читься ![alt text|500] или ![|500]. Вы поймёте, что всё сделали правильно, когда Обси­диан уменьшит размер картинки в за­метке.

Но есть одна загвоздка.

Пиксели в вебе ≠ пиксели изображения

Совет на сайте Бюро: «Почему ширина смартфонов при веб-разработке 320 пикселей?»

Кажется, что если указать ![alt text|500] — Обси­диан отрен­дерит тебе картинку шириной в 500 экранных пикселей шири­ной? Фигушки! Обси­диан рендерит заметки через ХТМЛ, а пик­сели в вебе отвя­заны от их физи­че­ских пред­ста­ви­те­лей. Это логич­но — иначе бы текст с кеглем 16 пикселей был бы абсо­лютно нечи­таем на 2K экранах смарт­фо­нов, где каждый физи­че­ский пиксель раз в 9 меньше пикселя на экране компью­тера. Не менее логично, что такие пиксели кличут логи­че­скими (или виртуальными).

Соот­но­шение физи­че­ских пикселей к ло­ги­че­ским назы­вают Device Pixel Ratio и де­вай­сов, где DPR равен единице, сейчас всё меньше. Из этого выте­кает следу­ю­щее: если вам нужен элемент шириной в 100 логи­че­ских пикселей с чётким изоб­ра­же­нием на фоне, вам почти никогда не хватит изоб­ра­жения шириной в 100 физи­че­ских пиксе­лей — нужно гене­ри­ро­вать набор изоб­ра­жений под разные DPR, а бра­узер поль­зо­ва­теля уже сам скачает нужный файл исходя из п­лот­ности пиксе­лей.

В коде это так:

<img src="image.jpg" srcset="image-1x.jpg 1x, image-2x.jpg 2x, image-3x.jpg 3x">

В 11ty пока нет опции «сге­не­рируй набор изоб­ра­жений под разные DPR», только опция «сге­не­рируй из этого файла набор изоб­ра­жений шириной в X, Y, Z пикселей и одно с изна­чальной шириной в таких-­то форма­тах». Более того, ширина и вы­сота изоб­ра­жения в фи­зи­че­ских пикселях пропи­сы­ва­ется в раз­меры его ХТМЛ-­элемента, где рабо­тают уже логи­че­ские пиксели. Резуль­тат — мутная картинка, зани­ма­ющая больше пиксе­лей, чем ей нужно.

Я не при­думал ничего лучше, чем прой­тись по всем сгене­ри­ро­ванным ХТМЛ-­файлам и умень­шить изна­чальную высоту и ши­рину для <img> тегов в два раза­ — так картинки будут очень хорошо выгля­деть на устрой­ствах с DPR в окрест­но­стях числа 2, а таких устрой­ств — боль­шин­ство.

Это всё ещё костыль, но это лучше, чем мыльные картинки. Приду­маю, что новое — дам вам знать.