Нативне відкладене завантаження для вебу

5 хв. читання

З новим атрибутом loading нативна підтримка відкладеного завантаження для <img> та <iframe> стане можливою.

Як це виглядає:

<img src="celebration.jpg" loading="lazy" alt="..." />
<iframe src="video-player.html" loading="lazy"></iframe>

Сподіваємось, що зовсім скоро Chrome 75 реалізує підтримку нової фічі. А поки що розглянемо особливості застосування loading.

Інтро

На веб-сторінці, зазвичай, розміщується велика кількість зображень, які впливають на використання даних, роздування сторінки та швидкість її завантаження. Більшість з цих зображень не знаходяться у полі зору користувача: він повинен скролити, щоб побачити їх.

Раніше для обмеження впливу таких зображень на час завантаження сторінки, розробники використовували JavaScript-бібліотеку (на зразок LazySizes), щоб відкласти завантаження цих зображень до їх появи у полі зору користувача.

Нативне відкладене завантаження для вебу
Сторінка завантажує 211 зображень. Версія без відкладеного завантаження використовує 10MB даних. Версія з відкладеним завантаженням (з використанням LazySizes) отримує тільки 250KB заздалегідь — інші зображення витягуються в міру прокрутки користувачем. Детальніше на WPT.

Якби ж браузер міг уникнути завантаження зображень поза полем зору? Так вміст частини сторінки, що переглядається, завантажувався б швидше, зменшувалося б загальне використання мережевих даних, зменшилося б використання пам'яті. На щастя, скоро все це можна буде реалізувати з новим атрибутом loading для <img> та <iframe>.

Детальніше про loading

Атрибут loading дозволяє браузеру відкласти завантаження зображення та iframe поза полем зору, поки користувач не прокрутить до певної позиції. loading підтримує три значення:

  • lazy: для відкладеного завантаження;
  • eager: завантажує все одразу;
  • auto: браузер самостійно визначає який варіант використовувати.

Якщо ви не встановите значення, за замовчуванням буде використовуватись auto.

Нативне відкладене завантаження для вебу

Приклади

Атрибут loading застосовується як для <img> (також з srcset та всередині <picture>), так і для <iframe>.

<!-- Відкладене завантаження зображення поза полем зору, коли користувач скролить до нього -->
<img src="unicorn.jpg" loading="lazy" alt=".."/>

<!-- Завантажує все одразу -->
<img src="unicorn.jpg" loading="eager" alt=".."/>

<!-- Браузер обирає варіант завантаження самостійно -->
<img src="unicorn.jpg" loading="auto" alt=".."/>

<!-- Відкладене завантаження у <picture>-->
<picture>
 <source media="(min-width: 40em)" srcset="big.jpg 1x, big-hd.jpg 2x">
 <source srcset="small.jpg 1x, small-hd.jpg 2x">
 <img src="fallback.jpg" loading="lazy">
</picture>

<!-- Відкладене завантаження зображення з визначеним srcset -->
<img src="small.jpg"
    srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w"
    sizes="(min-width: 36em) 33.3vw, 100vw"
    alt="A rad wolf" loading="lazy">

<!-- Відкладене завантаження для iframe -->
<iframe src="video-player.html" loading="lazy"></iframe>

Реалізацію визначення «коли користувач прокрутить до відповідного зображення» залишимо на браузер. Краще було б якби браузери отримували зображення та вміст iframe трохи раніше, ніж ці елементи попадуть у поле перегляду. Тобто зображення або iframe вже завершать завантаження, коли користувач прокрутить до них.

Зверніть увагу: пропонується назвати атрибут саме loading, тому що така логіка близька до атрибута decoding. Попередні пропозиції, на зразок lazyload, не забезпечують таку ж саму підтримку значень lazy, eager і auto.

Виявлення фіч

Варто пам'ятати про можливість використання JavaScript-бібліотеки для відкладеного завантаження (для крос-браузерної підтримки. Підтримку loading можна визначити таким чином:

<script>
if ('loading' in HTMLImageElement.prototype) { 
   // Браузер підтримує `loading`..
} else {
  // Отримайте та застосуйте поліфіл/JavaScript-біліотеку
  // для відкладеного завантаження.
}
</script>

Зверніть увагу: Ви також можете використовувати loading як поступове розширення. Браузери, що підтримують атрибут, реалізують поведінку відкладеного завантаження, якщо встановлено loading=lazy. В іншому випадку зображення завантажуватимуться як зазвичай.

Крос-браузерне відкладене завантаження зображень

Якщо для вас важлива крос-браузерність, вам не достатньо просто виявити підтримку фічі та завантажити потрібну бібліотеку, якщо ви використовуєте у вашій розмітці наступне: <img src="unicorn.jpg" loading="lazy" />.

В розмітці повинно бути щось подібне: <img data-src="unicorn.jpg" /> (а не src, srcset чи <source>), щоб уникнути eager-завантаження у браузерах, що не підтримують нового атрибуту. JavaScript можна використовувати для заміни таких атрибутів на правильні, якщо loading підтримується, а в іншому випадку завантажувати бібліотеку.

Розглянемо як це приблизно виглядатиме:

  • У полі зору розташовані зображення, визначені тегом <img>. Атрибут data-src переважає відкладене завантаження, тому ми уникаємо такий атрибут для зображень у полі зору.
  • Ми використовуємо data-src, щоб уникнути eager-завантаження у браузерах, які не підтримують відкладене завантаження. В іншому випадку, замінюємо data-src на src.
  • Якщо loading не підтримується, ми завантажуємо бібліотеку та ініціалізуємо її.

Для нашого прикладу ми використовуємо class=lazyload, щоб позначити зображення, які ми будемо завантажувати з LazySizes.

<!-- Завантажимо зображення у полі зору звичним чином -->
<img src="hero.jpg" alt=".."/>

<!-- Відкладене завантаження решти зображень -->
<img data-src="unicorn.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="cats.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="dogs.jpg" loading="lazy" alt=".." class="lazyload"/>

<script>
(async () => {
    const images = document.querySelectorAll("img.lazyload");
    if ('loading' in HTMLImageElement.prototype) {
        images.forEach(img => {
            img.src = img.dataset.src;
        });
    } else {
        // Динамічний імпорт бібліотеки LazySizes 
        const lazySizesLib = await import('/lazysizes.min.js');
        // Ініціалізація LazySizes (читає data-src & class=lazyload)
        lazySizes.init(); // lazySizes працює глобально.
    }
})();
</script>

Примітки

  • Спробуйте зараз: перейдіть у chrome://flags та оберіть пункути Enable lazy frame loading та Enable lazy image loading, і перезавантажте браузер.
  • DevTools: Особливість реалізації loading у Chrome в тому, що він отримує перші 2KB зображень при завантаженні сторінки. Решту зображень він підвантажує, коли користувач збирається їх побачити. Усе може закінчитися: (1) подвійним fetch на панелі DevTools Network та (2) Resource Timing для двох запитів кожного зображення.
Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.6K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація