Як сайти з чуйним дизайном завантажувати біса швидко

12

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

За останній рік я дуже багато часу приділив вивченню питання, пов’язаного з завантаженням сторінок як у рамках поточної роботи з клієнтами нашої компанії, так і з-за швидкого випуску моєї нової книги у видавництві A Book Apart. У процесі вивчення я ще раз переконався в тому, що у нас немає ніякої необхідності в тому, щоб жертвувати добре відомими перевагами чуйних сайтів, заради того, щоб вони стали біса швидко завантажуватися.

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

Я почну з загальних спостережень, а потім перейду вже до технічних прийомів. Спочатку, кілька моментів про процес завантаження сторінки і про те, яка наша кінцева мета.

Вага сторінки — це не єдиний показник; сфокусуйтеся на відчутною продуктивності

При обговоренні питання про те, як код, заточений під велику кількість пристроїв, впливає на процес завантаження сторінки, веб-розробники в якості одного з найголовніших показників, що впливають на успіх, виділяють загальний вага сторінки. Однак, ми хотіли б зазначити, що в той час як вага, розмір в байтах, наших сайтів збільшується (і це нагальна проблема – тарифні плани дорогі!), сам по собі вагу не обов’язково повинен збільшувати час, який користувач очікує, щоб почати користуватися сторінкою. Звичайно сторінка стає доступною для використання набагато раніше її повного завантаження. То як ми завантажуємо необхідні файли сайту також важливо, як і те, яку кількість файлів ми завантажуємо.

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

У той час як цей термін може показати суб’єктивним, відчутну продуктивність досить легко виміряти, і ми в змозі зробити дуже багато, щоб поліпшити цей показник, незалежно від того, чи є сайт чуйним чи ні. Для того щоб виміряти відчутну продуктивність, нам необхідно дізнатися, скільки часу буде потрібно на те, щоб сторінка стала відображатися в браузері. Сайт Webpagetest.org є чудовим інструментом, який ви можете використовувати саме для цієї мети. Просто зайдіть на цей сайт, введіть URL-адресу сайту, який ви хочете протестувати, та натисніть кнопку «Запустити тест».

Як сайти з чуйним дизайном завантажувати біса швидко

Сайт Webpagetest робить запит на зазначений сайт з реального браузера або пристрої, аналізує його завантаження і видає вам тонни інформації. Частина результатів, виданих сайтом Webpagetest безпосередньо відноситься до відчутної продуктивності, наприклад, пункт «Початок візуалізації», показники ви можете подивитися на наведеній нижче таблиці. Як бачите, рендеринг чуйного сайту компанії Filament починається в проміжку між 200 і 300 мілісекундами при звичайній швидкості з’єднання (до речі, це швидко! Як сайти з чуйним дизайном завантажувати біса швидко ).

Як сайти з чуйним дизайном завантажувати біса швидко

А ще ви можете подивитися рендеринг сторінок на покадрової тимчасової шкалою. Це дуже корисно для того щоб подивитися наскільки плавно в цілому відбувається процес завантаження сторінки. Наприклад, сайт Filament завантажує власні шрифти, іконки і фонові зображення після початку візуалізації. І ви можете побачити, як після початку візуалізації всі ці файли виникають в потрібному місці з кожним новим кадром (повна версія тимчасової шкали знаходиться тут).

Як сайти з чуйним дизайном завантажувати біса швидко

Щоб рендеринг складного макета був таким швидким, потрібно дуже ретельне обмірковування всіх рішень, тому давайте подивимося, як ми досягли такого результату.

Скорочуємо критичний шлях

Ви, напевно, чули про термін «критичний шлях», використовується для позначення проміжку часу між відправленням запиту до сторінки та її візуалізації. Я вважаю цей термін чудовою метафорою, оскільки він змушує мене уявити процес завантаження сторінки у вигляді шляху між пунктом А та пунктом Б, для проходження якої потрібно зробити певну кількість кроків. На щастя, багато з цих кроків нам підвладні. Наприклад, CSS і JavaScript запити можуть істотно збільшити час рендеринга сторінок. Це відбувається тому, що за замовчуванням браузери відкладають рендеринг сторінок, поки всі згадані в тегу head CSS і JavaScript файли будуть завантажені, оброблені і виконані.

Наприклад, ось деякі типові посилання на файли, які під час своєї завантаження, перешкоджають рендерингу сторінки:

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

АСИНХРОННЕ ЗАВАНТАЖЕННЯ

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


Але… атрибут async підтримується тільки останніми версіями браузерів (IE 10+), і елемент script не залишає нам ніякої можливості для визначення того, який запит повинен бути виконаний в першу чергу (ми зазвичай спочатку завантажуємо наш DOM-фреймворк, а після цього вже інші скрипти, які забезпечують підтримку різних можливостей). Для цих цілей зазвичай ми додаємо трохи JavaScript коду для асинхронного запитував наших файлів: для цієї мети ми використовуємо плагін loadJS. Далі показано, як після того, як ви один раз вставили плагін loadJS на сторінку, він буде використаний для того щоб запитувати будь-який скрипт (я урізав вихідний код плагіна):


// сюди вставляємо loadJS …
function loadJS( src ){ … }
// завантажуємо файл з loadJS
loadJS( «path/to/script.js» );

Що стосується асинхронного запитував CSS файлів: HTML не може запропонувати ніяких власних коштів для асинхронного запитував таблиці стилів, тому нам потрібно використовувати трохи JavaScript коду, щоб реалізувати і цей момент. Для цієї мети ми використовуємо плагін loadCSS.

Далі показано, як використовувати плагін loadCSS (і знову, вихідний код плагіна loadCSS урізаний):


// сюди вставляємо loadCSS …
function loadCSS( href ){ … }
// завантажуємо файл з loadCSS
loadCSS( «path/to/stylesheet.css» );

ВБУДОВАНИЙ (ІНЛАЙН), КОД

Іншим підходом, що дозволяє уникнути блокуючих запитів, є вставка вмісту тих файлів, які необхідно буде запитати, прямо в HTML-документ. Це також називається вбудовуванням. CSS файли можуть бути вбудовані в HTML-документ за допомогою елемента style, а JavaScript файли – з допомогою елемента script.


/* сюди поміщається вміст файлу a.js! */
/* сюди поміщається вміст файлу a.css! */

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

Тепер, коли у нас є кілька інструментів для більш швидкого завантаження CSS і JS, нам потрібно визначити код, який повинен бути вбудований в область head, а який код ми будемо запитувати ззовні.

Який код мені слід «вбудовувати»?

У деяких випадках, бажано, щоб не відбувався рендеринг сторінок, поки CSS і JavaScript не будуть оброблені. Наприклад, нам потрібно, щоб браузер завантажив весь необхідний для рендеринга сторінок CSS-код, перш ніж браузер почне сам рендеринг, тому що, якщо цього не відбудеться, то користувачі побачать неоформлений контент. Також, деякі скрипти на JavaScript працюють краще, якщо вони будуть виконані до рендеринга сторінок, наприклад, скрипт «HTML5 shim», який дозволяє старими версіями браузера IE розпізнавати нові елементи HTML (інші приклади: тестування можливостей і додавання класів).

Загалом, багато CSS і JS-коду може бути спокійно завантажено асинхронно, але звичайно не всі цілком. «Критичні» частини коду, потрібні для рендеринга, повинні бути вбудовані в HTML. Весь фокус полягає в тому, щоб правильно розбити код на частини для вбудовування і асинхронної завантаження.

ВКОРОЧУЄМО ДО 14

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

Тобто нам потрібно помістити необхідний для пункту «Початок візуалізації» HTML, CSS і JavaScript код в саме перше 14-килобайтное подорож.

Як сайти з чуйним дизайном завантажувати біса швидко

ВИЗНАЧАЄМО ВБУДОВАНИЙ CSS

Припустимо, що вся ваша таблиця стилів може бути вбудована в область head вашої сторінки, сумарна вага якої при цьому не буде перевищувати 14 кб (у стислому вигляді з gzip). В цьому випадку все досить просто. І тоді ви, швидше за все, вважатимете за краще вбудувати таблицю стилів у вашу сторінку і на цей зупинитися, т. к. ваша сторінка буде швидко завантажуватися і без яких-небудь інших додаткових дій.

Звичайно, на більшості сайтів, основна таблиця стилів сама по собі вже набагато перевищує розмір в 14 кб, і якщо це стосується й вашого сайту, то вам буде потрібно виділити «критичну» частина ваших стилів і вбудувати тільки її, залишивши решту для асинхронної завантаження. В даний час веб-розробникам доступний цілий ряд нових інструментів, здатних впоратися з цим завданням. Одним з таких інструментів, яким ми самі користуємося і застосовуємо на сайті нашої компанії, є Grunt Critical CSS.

Завдання нашого інструменту Grunt Critical CSS полягає в тому, щоб відкрити сторінку в браузері з командного рядка, підлаштувати ширину вікна під певні параметри ширини і висоти (за замовчуванням це 1200 x 900) і проаналізувати, які стилі застосовуються до елементів, які відображаються у видимій частині вікна перегляду. Потім Grunt Critical CSS записує ці стилі в окремий файл, який ви зможете використовувати для вбудовування на будь-якій сторінці. На рисунку показано, для якої області сторінки нам потрібно вбудувати критичний CSS – Grunt Critical CSS згенерував стилі, які необхідні для візуалізації верхній частині сторінки, і вмонтував їх в область head нашої сторінки (інші стилі буду завантажені асинхронно).

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

Як сайти з чуйним дизайном завантажувати біса швидко

Для того щоб дати завдання інструменту Grunt Critical CSS, ви повинні мати загальне уявлення про те, як ставляться завдання в Grunt (інформацію ви можете знайти на сайті проекту Grunt). Потім потрібно зробити базові налаштування. Для цього ми ставимо окрему задачу для кожного основного шаблону нашого сайту (головна, про нас, портфоліо тощо) для того, щоб згенерувати файл з критичним CSS для кожного шаблону окремо. Далі ми вбудовуємо отриманий CSS в кожен шаблон на стороні сервера. Ось невеликий фрагмент налаштувань:

criticalcss: {
home: {
options: {
пропустити, результати : ‘css/critical/critical-home.css’,
filename : ‘all.css’,
url : ‘http://fgwebsite.local’
}
},
services: {
options: {
пропустити, результати : ‘css/critical/critical-services.css’,
filename : ‘all.css’,
url : ‘http://fgwebsite.local/services/’
}
},
about: {

В даних параметрах ми вказуємо файл «all.css», тобто це головна таблиця стилів для всього сайту, яка і буде аналізуватися в ході виконання завдання. Під час процесу завантаження сторінки дана таблиця стилів буде асинхронно завантажуватися за допомогою loadCSS.

Примітка: вам також ознайомитися з завданням Critical Node.js, яке створив Едді Османі (Addy Osmani). Воно було створене вчасно складання даній статті. А також познайомтеся з завданням Penthouse, яке створив Джонас Охлсон (Jonas Ohlsson).

ВИЗНАЧАЄМО ВБУДОВАНИЙ JS

Що стосується JavaScript, то зазвичай ми відокремлюємо критичний і не критичний код шляхом ручного складання окремих файлів. Ми прагнемо зробити наш JavaScript код настільки коротким і лаконічним, наскільки це можливо. Тому в цьому коді зазвичай містяться тільки перевірка можливостей і скрипти, які полегшують завантаження додаткових файлів. Решті JavaScript код, в якому зазвичай міститься DOM фреймворк, наприклад, jQuery і різні віджети користувальницького інтерфейсу, поміщаються в один «покращений» JavaScript файл, який буде завантажуватися асинхронно браузерами, здатними на це.

І оскільки останнім часом ми використовуємо даний підхід для кожного проекту, ми створили оновлену версію нашого проекту Enhance, який служить в якості шаблону для JavaScript коду, який ми зазвичай включаємо в область head нашої сторінки. Друга версія Enhance.js вже не вважається бібліотекою або фреймворком. Скоріше це невеликий легко редагований файл, який можна підлаштувати під потреби вашого проекту. За замовчуванням у файлі enhance.js містяться також і інші наші скрипти, наприклад, loadJS і loadCSS, а також невеликий алгоритм для організації правильної роботи скриптів.

Ми використовуємо Enhance.js, щоб проводити невелику браузерну діагностику, перш ніж вирішити, чи потрібно покращувати базову, але вже функціональну сторінку шляхом додавання класів і запитував додаткових скриптів і таблиць стилів. Якщо ви раптом пам’ятайте написану мною в 2008 році статтю або ж вам знайоме сучасне вираз «задовольняє вимогам», придумане на каналі BBC Томом Олійному (Tom Maslen), тоді цей процес буде вам знаком.
За замовчуванням Enhance.js налаштований для виконання наступних кроків:

Визначає змінні і функції для завантаження файлів і забезпечення доступу до інформації про браузері і розмітки.

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

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

У коді цей перевірочний тест або тест під назвою «задовольняє вимогам») часто виглядає як ось цей невеликий фрагмент коду, який перевіряє, чи підтримуються можливості querySelector і addEventListener. (тести на перевірку конкретних можливостей змінюються від проекту до проекту):

if( «querySelector» in document &&
document.addEventListener.) {
// здатний! продовжуємо поліпшення

..після чого ми зазвичай додаємо клас .enhanced до html-елемента для розширених CSS можливостей і завантажуємо наш покращений JavaScript файл.

Збираємо всі разом

Тепер, знаючи про даних підходах, ми можемо повернутися до початку нашої розмови і подивитися, як можна сконфігурувати область head для наших сторінок. На нашому сайті (filamentgroup.com ми починаємо з вказівки деяких мета-тегів, які визначають шляхи до наших CSS і JS файлів (вони знадобляться для завантаження файлів з JS), а потім включаємо вбудований JavaScript і CSS код, про який мова йшла вище. І нарешті, ми вказуємо посилання на головну таблицю стилів за допомогою звичайної посилання всередині елемента noscript, щоб забезпечити її завантаження тільки в тих випадках, коли JavaScript буде відключений. Ось спрощений приклад конфігурації, використовуваної на нашому сайті:


Завдяки нашому критичного CSS і JS кодом, вбудованому в область head нашої сторінки, ми можемо асинхронно завантажити інші файли і забезпечити тим самим грамотну і швидке завантаження нашої сторінки.

ВИГІДНО ВИКОРИСТОВУЄМО КЕШ

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

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

Ви можете більше дізнатися про даному підході з опису до проекту.

Порівнюємо вигоди

Просто заради порівняння, я створив тестовий варіант нашої головної сторінки, де CSS і JavaScript файлів стандартним (блокується рендеринг) способом, і перевірив цей варіант з допомогою сервісів Page Speed Insights» і «WebPageTest». Наша головна сторінка являє собою відносно простий макет, тому я не очікував, що результати тестів будуть дуже жахливими, але я виявив, що результати підтвердили безсумнівну вигоду від застосування наших рекомендацій, особливо коли умови для перегляду веб-сторінок не є ідеальними.

По-перше, в той час як справжня версія нашого сайту набирає зараз 100/100 на сервісі Page Speed Insights, «поганий» варіант набирає 72/100 для мобільних екранів і 88/100 для великих «десктопних» екранів.

Результати на сервісі Page Speed Insights без проведення оптимізації:

Як сайти з чуйним дизайном завантажувати біса швидко

Далі, результати на сервісі WebPage Test представлені у вигляді таблиці. Середній показник пункту «Початок візуалізації» при швидкому з’єднанні виріс на 900 мілісекунд, що є досить гарним результатом, хоча він гірше, ніж показник нашого реального сайту (295 мілісекунд). Звичайно, це за умови, що все працює добре; що більше всього турбує при даному підході так це показники, отримані при нестабільному або слабкому з’єднанні. Наприклад, під час однієї з перевірок нашого тестового сайту, деяких файлів для завантаження знадобилося більше секунди, а для завантаження самої сторінки знадобилося більше 2,5 секунд!

Результати на сервісі WebPageTest без проведення оптимізації:

Як сайти з чуйним дизайном завантажувати біса швидко

Тут слід пам’ятати про те, що дані тести на сервісі WebPageTest були проведені при стабільному кабельному з’єднанні з пропускною спроможністю 5 Мбіт/с, тому можна сміливо припустити, що ефект від блокуючих рендеринг запитів був би набагато більш помітним при звичайному мобільному 3G-з’єднання.

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