Детальний опис техніки ледачого завантаження зображень (Lazy Load)

Детальний опис техніки ледачого завантаження зображень (Lazy Load)



Ліниве (або відкладене) завантаження картинок – це популярний метод асинхронного звернення до адреси зображення, по мірі необхідності його завантаження, а не одразу після того, як HTML сторінки був проаналізований браузером. Ви, швидше за все, вже бачили цю реалізацію в дії, оскільки цей метод використовується на багатьох популярних сайтах.

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

Зворотною стороною медалі є те, що графічні елементи і медіа-дані (картинки, відео, аудіо) – це дуже «важкі» файли, які уповільнюють швидкість завантаження сторінки.

Виходить, що нам всім потрібні картинки, але ми повинні подбати і про швидкість завантаження сайту, на якому ці картинки розміщуються. В сьогоднішньому практичному посібнику ми розглянемо всі основні моменти Lazy Load завантаження зображень (техніка «ледачого» або відкладеного завантаження). Цей метод дозволяє скоротити час завантаження сторінки сайту, відкладаючи завантаження зображень до того моменту, коли вони будуть потрібні.

 

Сьогодні ми розглянемо такі пункти:

  • Що таке ліниве завантаження (Lazy Load) зображень і як воно працює?
  • Теорія реалізації відкладеного завантаження
  • Практичні приклади досягнення відкладеного завантаження:
    • з допомогою подій JavaScript
    • з допомогою API Intersection Observer
  • Залежність відкладеного завантаження від JavaScript
  • Популярні JavaScript бібліотеки для ледачого завантаження
  • Як протестувати відкладене завантаження?

 

Ось що ми будемо сьогодні реалізовувати:

 

 

 

Що таке ліниве завантаження (Lazy Load) зображень і як воно працює?

Замість того, щоб завантажувати всі зображення одночасно, Lazy Load завантаження завантажує тільки ті зображення, які видно на екрані користувача. А всі інші зображення замінюються заповнювачем (наприклад, заливкою кольором або розмитою копією зображення низької якості).

Коли користувач прокручує сторінку вниз, сайт завантажує зображення, які в даний момент видно в області перегляду браузера.

 

Слово «ледачий» у нас асоціюється з людиною, яка якомога довше уникає роботи, або у якої явне бажання взагалі нічого не робити.

В даному ж контексті мова йде про те, що ліниве завантаження відкладає завантаження ресурсів на сторінці до тих пір, поки вони не потрібні. Замість того, щоб завантажувати зображення на сторінці одразу, ми дозволяємо їм завантажуватися пізніше, коли ці ресурси дійсно будуть потрібні. Тому, дана техніка називається ледачим або відкладеним завантаженням (Lazy Load).

Техніка відкладеного завантаження може застосовуватися не тільки до картинок, але й практично до будь-яких ресурсів на сторінці. Це можуть бути JavaScript файли, відео, iframe та навіть текст.

 

Ефективність техніки ледачого завантаження

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

Якщо ми не завантажуємо картинки на сторінці, відповідно ця сторінка буде завантажуватися швидше. Оскільки браузер не буде завантажувати ці картинки з сервера, сайт буде рендеритись (візуалізуватися) швидше. Також це гарантує, що на сервер буде менше навантаження.

 

 

Теорія реалізації відкладеного завантаження

Типова HTML-розмітка для зображення виглядає так:

<img src="/{шлях до картинки}/image.jpg" />

 

Браузер використовує атрибут src тега img, щоб знайти адресу зберігання зображення і почати його завантаження. Коли браузер отримує атрибут src, він запускає одночасне завантаження всіх зображень на сторінці. І неважливо, скільки картинок ви розмістили на сторінці: одну або тисячу.

Відповідно, перша задача для досягнення відкладеного завантаження – це запобігти завантаженню зображень. Щоб відкласти завантаження, потрібно помістити URL-адресу зображення в атрибут, який відрізняється від src. Припустимо, якщо для цих цілей ми будемо використовувати атрибут data-src, тоді код буде виглядати так:

<img data-src="/{шлях до картинки}/image.jpg" />

 

Тепер, коли атрибут src порожній, браузер не буде запускати завантаження зображення.

Після цього нам потрібно повідомити браузеру, коли потрібно запускати завантаження. В іншому випадку цього ніколи не станеться. Ми перевіряємо входження зображення (тобто, його заповнювача) в область перегляду (видиму частину екрану), після чого запускаємо завантаження.

Є два способи перевірити, коли зображення потрапляє в видиму частину екрану. Давайте розглянемо ці способи на практиці, з прикладами робочого коду.

 

 

Практичні приклади досягнення відкладеного завантаження

Розглянемо практичні приклади досягнення відкладеного завантаження для зображень.

 

Спосіб №1: Відкладене завантаження зображення з допомогою подій JavaScript

Цей метод використовує слухачі подій в браузері для подій scroll, resize і directionChange. Подія прокрутки (scroll) є досить ефективною, оскільки вона відстежує, де користувач знаходиться на сторінці, коли відбувається прокрутка. Події resize (зміна розміру вікна браузера) і directionChange (поворот пристрою з альбомного в портретний, і навпаки) також досить ефективні.

Ми можемо використовувати ці три події, щоб розпізнати зміни на екрані та визначити кількість зображень, які стають видимими на екрані, і відповідно ініціювати їх завантаження. Коли відбувається будь-яка з цих подій, ми знаходимо всі зображення на сторінці, що не були завантажені (були відкладені), і на основі цих зображень ми перевіряємо, які з них в даний час знаходяться в області перегляду. Це робиться з використанням верхнього зміщення зображення, поточної верхньої позиції документа і висоти вікна. Якщо зображення увійшло в область перегляду, ми вибираємо URL з атрибуту data-src і переміщаємо його в атрибут src, в результаті чого зображення завантажується.

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

Коли ми прокручуємо сторінку, подія прокрутки спрацьовує кілька разів і швидко. Таким чином, потрібно додати невеликий тайм-аут в скрипт, який буде обмежувати виконання відкладеного завантаження, щоб він не блокував інші завдання, які виконуються в тому ж потоці.

Ось робочий приклад цього підходу:

<style>
/* заповнювач для картинок */
img {
 background: #ccc;
 width: 1920px;
 height: 1080px;
 display: block;
 margin: 10px auto;
 border: 0;
}
</style>
<p><img src="https://picsum.photos/id/5/1920/1080" /></p>
<p><img class="lazy" data-src="https://picsum.photos/id/15/1920/1080" /></p>
<p><img class="lazy" data-src="https://picsum.photos/id/25/1920/1080" /></p>
<p><img class="lazy" data-src="https://picsum.photos/id/35/1920/1080" /></p>
<p><img class="lazy" data-src="https://picsum.photos/id/55/1920/1080" /></p>
<script>
document.addEventListener("DOMContentLoaded", function() {
 var lazyloadImages = document.querySelectorAll("img.lazy");
 var lazyloadTimeout;
 function lazyload() {
  if(lazyloadTimeout) {
   clearTimeout(lazyloadTimeout);
  }
  lazyloadTimeout = setTimeout(function() {
   var scrollTop = window.pageYOffset;
   lazyloadImages.forEach(function(img) {
    if(img.offsetTop < (window.innerHeight + scrollTop)) {
     img.src = img.dataset.src;
     img.classList.remove('lazy');
    }
   });
   if(lazyloadImages.length == 0) {
    document.removeEventListener("scroll", lazyload);
    window.removeEventListener("resize", lazyload);
    window.removeEventListener("orientationChange", lazyload);
   }
  }, 50);
 }
 document.addEventListener("scroll", lazyload);
 window.addEventListener("resize", lazyload);
 window.addEventListener("orientationChange", lazyload);
});
</script>

 

 

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

 

 

Спосіб №2: Відкладене завантаження зображення з допомогою API Intersection Observer

Intersection Observer API з’явився відносно недавно. Цей прикладний програмний інтерфейс спрощує процес виявлення моменту, коли елемент з’являється в області перегляду, і спрощує виконання дії, коли ця подія відбувається. У попередньому методі нам доводилося пов’язувати події, пам’ятати про продуктивність і реалізовувати спосіб обчислення, чи перебував елемент в області перегляду чи ні. API Intersection Observer не має недоліків попереднього способу, а також забезпечений відмінною продуктивністю.

Нижче наведено робочий приклад використання API для відкладеного завантаження зображень.

<style>
/* заповнювач для картинок */
img {
 background: #ccc;
 width: 1920px;
 height: 1080px;
 display: block;
 margin: 10px auto;
 border: 0;
}
</style>
<p><img src="https://picsum.photos/id/5/1920/1080" /></p>
<p><img class="lazy" data-src="https://picsum.photos/id/15/1920/1080" /></p>
<p><img class="lazy" data-src="https://picsum.photos/id/25/1920/1080" /></p>
<p><img class="lazy" data-src="https://picsum.photos/id/35/1920/1080" /></p>
<p><img class="lazy" data-src="https://picsum.photos/id/55/1920/1080" /></p>
<script>
document.addEventListener("DOMContentLoaded", function() {
 var lazyloadImages;
 if ("IntersectionObserver" in window) {
  lazyloadImages = document.querySelectorAll(".lazy");
  var imageObserver = new IntersectionObserver(function(entries, observer) {
   entries.forEach(function(entry) {
    if (entry.isIntersecting) {
     var image = entry.target;
     image.src = image.dataset.src;
     image.classList.remove("lazy");
     imageObserver.unobserve(image);
    }
   });
  });
  lazyloadImages.forEach(function(image) {
   imageObserver.observe(image);
  });
 } else {
  var lazyloadTimeout;
  lazyloadImages = document.querySelectorAll(".lazy");
  function lazyload() {
   if(lazyloadTimeout) {
    clearTimeout(lazyloadTimeout);
   }
   lazyloadTimeout = setTimeout(function() {
    var scrollTop = window.pageYOffset;
    lazyloadImages.forEach(function(img) {
     if(img.offsetTop < (window.innerHeight + scrollTop)) {
      img.src = img.dataset.src;
      img.classList.remove('lazy');
     }
    });
    if(lazyloadImages.length == 0) {
     document.removeEventListener("scroll", lazyload);
     window.removeEventListener("resize", lazyload);
     window.removeEventListener("orientationChange", lazyload);
    }
   }, 50);
  }
  document.addEventListener("scroll", lazyload);
  window.addEventListener("resize", lazyload);
  window.addEventListener("orientationChange", lazyload);
 }
})
</script>

 

 

Тут ми прикріплюємо спостерігач до всіх зображень, які потрібно завантажувати «ліниво». Як тільки API виявляє, що елемент увійшов в область перегляду, використовуючи властивість isIntersecting, ми витягаємо URL з атрибуту data-src і переміщуємо його в атрибут src, щоб ініціювати завантаження зображення в браузері. Після цього ми видаляємо у зображення клас lazy, а також видаляємо спостерігача для цього зображення.

Важливо! Врахуйте, що підтримка API Intersection Observer може бути недоступною в деяких браузерах.

 

 

Залежність відкладеного завантаження від JavaScript

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

 

 

Популярні JavaScript бібліотеки для ледачого завантаження

Оскільки середовище розробки і деталі реалізації можуть відрізнятися в різних браузерах і на різних пристроях, ви можете використовувати перевірені JavaScript бібліотеки для відкладеного завантаження, а не створювати що-небудь з нуля для цього.

Розглянемо кращі та найпопулярніші скрипти, які використовуються для відкладеного завантаження, і які дозволять зробити це з мінімальними зусиллями. А більшість з них роблять відкладене завантаження не тільки картинок, але й відео, об’єктів iframe, простого тексту та інших елементів.

(бібліотеки представлені в алфавітному порядку)

  • BLazy.js
  • Echo.js
  • lazySizes
  • jQuery Lazy
  • jQuery Lazy Load XT
  • yall.js (Yet Another Lazy Loader)

 

 

 

Як протестувати відкладене завантаження?

Після того, як ви впровадили відкладене завантаження, ви, ймовірно, захочете переконатися, що воно працює так, як задумано. Найпростіший спосіб – відкрити інструменти розробника в вашому браузері (натисніть F5 або Ctrl+Shift+I).

Звідти перейдіть в Мережа > Зображення (Network > Images). Оновіть сторінку і ви повинні побачити тільки завантажені зображення в цьому списку.

Потім, коли ви почнете прокручувати сторінку вниз, спрацюють інші запити і будуть завантажені решта картинок.

 

 

 

Підбиття підсумків

Сьогодні ми розглянули багато питань, які стосуються ледачого завантаження картинок. Ліниве (або відкладене) завантаження, якщо воно реалізовано правильно, може значно підвищити продуктивність вашого сайту, збільшити швидкість завантаження сторінки, а також знизити навантаження на сервер.

Оскільки зображення є основним фактором, що впливає на час завантаження веб-сторінок, ліниве завантаження зображень – це підхід, який ви можете ефективно використовувати на своєму сайті.

Сподіваємося, що сьогоднішня інформація була для вас практично корисною і потрібною. Дякуємо, що читаєте нас!

 



Напишіть тут свою думку/питання

Ваша пошта не публікуватиметься. Обов’язкові поля позначені *