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

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

Для инте­ре­су­ю­щихся: изоб­ра­жения в 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, а таких устройств — боль­шин­ство.

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