Підвищуємо продуктивність: як завантажувати зображення за допомогою in-view.js

28

Від автора: у цьому уроці я покажу вам, як підвищити продуктивність веб-сторінок за допомогою in-view.js. Ця JS бібліотека посилає відповідь, коли що-небудь потрапляє у видиме вікно браузера під час прокручування сторінки. З її допомогою ми зможемо динамічно завантажувати зображення тоді, коли вони потрібні.

Продуктивність має значення

Веб-продуктивність відіграє велику роль, особливо якщо ваш сайт націлений на країни, що розвиваються, з повільним інтернетом і дорогими тарифними планами. Серед стандартних завдань з підвищення продуктивності, які ми вживаємо, можна виділити минификацию JS файлів і стилів, стиснення медіа файлів, зменшення зображень. Якщо виконати всі ці маніпуляції, наш сайт отримає значний приріст продуктивності. Але чи це так?

Повышаем производительность: как загружать изображения при помощи in-view.js

У прикладі вище в інспекторі показано, як одна сторінка завантажує 24 зображення на мобільному пристрої з звичайною швидкістю 3G. Як ми бачимо, повне завантаження сторінки займає близько 11 секунд! Це дуже повільно, якщо врахувати, що на сторінці всього кілька зображень і файли стилів. Сторінка не захаращена рекламою, відстежувальними скриптами, які зазвичай додають сторінку у вазі.

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

Так як же підвищити продуктивність завантаження сторінок?

Вузьке місце

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

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

Починаємо

Щоб далі працювати, скачайте index-starter.html з репозиторію. Також там лежить файл стилів css/styles-starter.css, можете ним скористатися.

Насамперед, нам потрібно замінити зображення на дуже маленькі, переважно закодовані в base64, щоб уникнути зайвих HTTP запитів. Ці зображення будуть грати роль плейсхолдеров перед завантаженням повноцінних зображень. Справжні зображення ми будемо зберігати в користувальницькому атрибуті data-src.

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

Повышаем производительность: как загружать изображения при помощи in-view.js

Давайте виправимо стилі.

Зберігати співвідношення сторін зображень

Наші реальні зображення мають розмір 800 на 550 пікселів. Розділимо висоту зображення (800px) на його ширину (500px) і помножити результат на 100%. Отримане значення використовуємо як padding top для псевдоэлемента контейнера зображення. Нам залишилося визначити зображенню абсолютне позиціонування і максимальну висоту на 100%. Так висота зображення не буде зберігатися.

figure {
position: relative;
}
figure img {
top: 0;
left: 0;
position: absolute;
max-height: 100%;
}
figure:before {
padding-top: 69.25%; // ( 554 / 800 ) * 100%
}

Тепер розміри зображення повинні бути правильними. Однак реальне зображення лежить в основі атрибуті, тобто браузер поки що не завантажив жодного зображення.

Повышаем производительность: как загружать изображения при помощи in-view.js

Зображення з правильним співвідношенням сторін, саме зображення завантажується

Завантажуємо зображення

По-перше, на сторінку потрібно завантажити in-view.js. Вище вже говорилося, що це легка бібліотека (не залежить від JQuery і таких базових бібліотек, як Waypoints) визначає, потрапив елемент у видиму область вікна браузера або немає.

Створіть JS файл, в якому ми будемо писати код, і підключіть його після in-view.js як показано нижче:

Методи та функції

У бібліотеці in-view.js є функція inView(), що приймає в якості аргументу селектор. В нашому випадку ми будемо передавати елемент figure, елемент, який обертає зображення. Ми вибрали контейнер, тому що ми пропишемо пару класів для плавних переходів. Це значно простіше зробити, коли клас присвоєно змінній, а не самому зображенню.

inView(‘figure’)

Потім за допомогою методу .on() ми присвоїмо елементу подія enter для перевірки, чи потрапив елемент в область видимості. Також в in-view.js є подія exit, яке виконує протилежну перевірку. Воно визначає, коли елемент зник з видимої області.

inView( ‘figure’ ).on( ‘enter’, function( figure ) {
var img = figure.querySelector( ‘img’ ); // 1
if ( ‘undefined’ !== typeof img.dataset.src ) { // 2
figure.classList.add( ‘is-loading’ ); // 3
// 4
newImg = new Image();
newImg.src = img.dataset.src;
newImg.addEventListener. ( ‘load’, function() {
figure.innerHTML = «; // 5
figure.appendChild( this );
// 6
setTimeout( function() {
figure.classList.remove( ‘is-loading’ );
figure.classList.add( ‘is-loaded’ );
}, 300 );
} );
}
} );

Подія enter буде запускати функцію, яка буде:

вибирати зображення всередині тега figure;

перевіряти в ньому атрибут data-src;

додавати клас is-loading до контейнера, тобто тегу figure;

завантажувати нове зображення за посиланням, отриманої з атрибута data-src;

після завантаження вставляти зображення в контейнер;

і нарешті, буде замінювати клас is-loading на is-loaded.

Завантажуємо що хочемо

У коді вище з’явилося два нових класу, is-loading і is-loaded. З допомогою класу is-loading ми додаємо спиннер анімацію на час завантаження зображення. З імені другого класу ясно, що він додається після завантаження зображення, щоб плавно показати його.

figure.is-loaded img {
animation: fadeIn 0.38 s linear 1s forwards;
}
figure.is-loading {
position: relative;
}
figure.is-loading:after {
content: «;
display: block;
color: #ddd;
font-size: 30px;
text-indent: -9999em;
overflow: hidden;
width: 1em;
height: 1em;
border-radius: 50%;
margin: auto;
position: absolute;
top: 50%;
left: 50%;
margin-left: -0.5 em;
margin-top: -0.5 em;
transform: translateZ(0);
animation: loading 1.7 s infinite ease;
}
@keyframes loading {
0% {
transform: rotate(0deg);
box-shadow: 0 -0.83 em 0 -0.4 em, 0 -0.83 em 0 -0.42 em, 0 -0.83 em 0 -0.44 em, 0 -0.83 em 0 -0.46 em, 0 -0.83 em 0 -0.477 em;
}
5%,
95% {
box-shadow: 0 -0.83 em 0 -0.4 em, 0 -0.83 em 0 -0.42 em, 0 -0.83 em 0 -0.44 em, 0 -0.83 em 0 -0.46 em, 0 -0.83 em 0 -0.477 em;
}
10%,
59% {
box-shadow: 0 -0.83 em 0 -0.4 em, -0.087 em -0.825 em 0 -0.42 em, -0.173 em -0.812 em 0 -0.44 em, -0.256 em -0.789 em 0 -0.46 em, -0.297 em -0.775 em 0 -0.477 em;
}
20% {
box-shadow: 0 -0.83 em 0 -0.4 em, -0.338 em -0.758 em 0 -0.42 em, -0.555 em -0.617 em 0 -0.44 em, -0.671 em -0.488 em 0 -0.46 em, -0.749 em -0.34 em 0 -0.477 em;
}
38% {
box-shadow: 0 -0.83 em 0 -0.4 em, -0.377 em -0.74 em 0 -0.42 em, -0.645 em -0.522 em 0 -0.44 em, -0.775 em -0.297 em 0 -0.46 em, -0.82 em -0.09 em 0 -0.477 em;
}
100% {
transform: rotate(360deg);
box-shadow: 0 -0.83 em 0 -0.4 em, 0 -0.83 em 0 -0.42 em, 0 -0.83 em 0 -0.44 em, 0 -0.83 em 0 -0.46 em, 0 -0.83 em 0 -0.477 em;
}
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}

Фолбэк

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


Ми закінчили! Оновіть сторінку. Якщо тепер проінспектувати тимчасову лінію на вкладці мережу в панелі розробника, можна побачити, що швидкість завантаження значно зросла, так як ми завантажуємо тільки те, що бачить користувач.

Повышаем производительность: как загружать изображения при помощи in-view.js

Тепер сторінка завантажується всього за 1.95 секунди на звичайному 3G з’єднання. Приріст продуктивності більш ніж на 500%!

Висновок

У цій статті ми дізналися, як підвищити швидкість завантаження сторінок, отрисовывая зображення тільки по мірі їх потреби користувача. Метод також відомий, як «ледача завантаження», і може багаторазово підвищити продуктивність.

Існує безліч JS бібліотек і JQuery плагінів, які роблять те ж саме. Чому саме in-view.js? Особисто для мене, in-view.js був скриптом, який я шукав, бо він виконує тільки те, що від нього вимагається. Він призначений для єдиної мети і добре з нею справляється. Така бібліотека дає вам більше контролю та гнучкості.

Наприклад, in-view.js можна використовувати не тільки для ледачої завантаження, але також і для створення нескінченного скролу, відображення плаваючою форми підписки, коли користувач долистывает до кінця сторінки (подивіться демо) або для створення вертикального таймлайна без необхідності підключати ще одну JS бібліотеку. А як ви використовуєте цю бібліотеку?

Повышаем производительность: как загружать изображения при помощи in-view.js

Плаваюча форма підписки, плавно з’являється, коли користувач прокручує сторінку до кінця.