Ranyboskie!

Obrazki w formatach nowej generacji które zadziałają wszędzie

TL;DR:


W czym jest problem?

Obrazki mogą w znacznym stopniu przyczynić się do spadku wydajności stron internetowych. Aby temu zapobiec warto rozważyć ich serwowanie w alternatywnych formatach, takich jak WebP i JPG2000, które, przy zachowaniu porównywalnej jakości są dużo lżejsze i pozwalają na zastosowanie mocniejszej kompresji.

Porównajmy przykładowe rozmiary tego samego zdjęcia w różnych formatach i przy różnych stopniach kompresji:

Format Kompresja Rozmiar
WebP 60 15 KB
JPEG 2000 39 18 KB
JPG 70 32 KB

Problemem jest jedynie to, że niektóre formaty nie zadziałają w każdej przeglądarce. Chrome i Firefox poradzą sobie z WebP, ale nie będą w stanie wyświetlić JPEG 2000, natomiast na Safari sytuacja wygląda odwrotnie.

Poniżej możesz zobaczyć trzy zdjęcia Karłątka Kniejnika, osadzone najzwyklejszym w tagu <img>.
Pierwszy jest w formacie WebP, drugi to JPEG 2000, trzeci w końcu, to stary dobry JPG.

karłątek kniejnik w formacie WebP
karłątek kniejnik w formacie JPEG 2000
karłątek kniejnik w formacie JPG

Otwierając ten przykład w różnych przeglądarkach możesz zaobserwować, że zawsze przynajmniej jeden obrazek nie wyświetla się poprawnie.

Jak to zrobić?

Najlepszym rozwiązaniem jest zaserwowanie wszystkich formatów jednocześnie w tagu <picture>. W tagu <picture> można umieścić wiele alternatywnych plików źródłowych używając tagu <source>. W takiej sytuacji przeglądarka sama wybierze najlepszy dla siebie obrazek.

Wygląda to mniej więcej tak:

<picture>
<source srcset="/img/posts/next-gen-img/motylek.webp" type="image/webp">
<source srcset="/img/posts/next-gen-img/motylek.jp2" type="image/jp2">
<img src="/img/posts/next-gen-img/motylek.jpg" alt="karłątek kniejnik w tagu picture">
</picture>

Dwa pierwsze tagi <source> zostaną wyświetlone zależnie od tego jaki format grafiki jest wspierany przez przeglądarkę, natomiast jeśli przeglądarka nie wspiera ani elementu <picture>, ani żadnego z formatów nowej generacji, wyświetlony zostanie obrazek w formacie JPG z tagu <img>. Takie rozwiązanie zadziała właściwie wszędzie.

W praktyce wyglądać to będzie tak:

karłątek kniejnik w tagu picture

Jak to zautomatyzować?

Proces optymalizacji grafik może być czasochłonny, więc warto go zautomatyzować.
W poniższym przykładzie użyłem paczki gm (npm i gm) dzięki której można używać pakietu imagemagick z poziomu Node.js.

Aby skrypt zadziałał wymagane jest zainstalowanie imagemagic:
brew install imagemagick - OS X
imagemagick.org/script/download - Windows i Linux

Teraz wystarczy tylko stworzyć plik JavaScript, wkleić do niego poniższy skrypt i podmienić ścieżkę do oryginalnego zdjęcia i nazwę dla zoptymalizowanego pliku.

const fs = require('fs');
const gm = require('gm');

const originalImg = 'original.jpg';
const optimizedName = 'optimized';

gm(originalImg)
.noProfile()
.resize(1000, 1000)
.quality(70)
.write(`${optimizedName}.jpg`, (err) => {
if (!err) console.log('done');
else console.log(err);
});

gm(originalImg)
.noProfile()
.resize(1000, 1000)
.quality(60)
.write(`${optimizedName}.webp`, (err) => {
if (!err) console.log('done');
else console.log(err);
});

gm(originalImg)
.noProfile()
.resize(1000, 1000)
.quality(39)
.write(`${optimizedName}.jp2`, (err) => {
if (!err) console.log('done');
else console.log(err);
});

Po odpaleniu skryptu w bieżącym katalogu zostaną utworzone zdjęcia w formatach WebP, JPEG 2000 oraz JPG.

← Wróć