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

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

Зображення

Забезпечити потрібний розмір

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

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

Де насправді вистачило б і картинки 200 на 200 пікселів. Якщо вихідний файл має розмір близько 1 Мб, а у нас списку існує десять позицій, то тільки при завантаженні зображень користувачеві доведеться викачати 10 Мб.

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

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

@media only screen
and (min-device-width : 320px)
and (max-device-width : 480px) {
.header {
background-image: url(../images/background_400x200.jpg);
}
}

Стиснення

Завантаження зображення з застосуванням налаштувань потрібного розміру не завжди достатньо. Файли деяких форматів можуть бути значно зменшені, при цьому без втрати якості. Є багато програм, які можуть вам у цьому допомогти. Наприклад, Photoshop підтримує відмінну функцію «Зберегти для Веб і інших пристроїв»:

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

Звичайно, можна використовувати для стиснення файлів код, але я особисто віддаю перевагу Photoshop. Його я використовую завжди, коли є така можливість. Нижче наводиться простий приклад коду PHP:

function compressImage($source, $destination, $quality) {
$info = getimagesize($source);
switch($info[‘mime’]) {
case «image/jpeg»:
$image = imagecreatefromjpeg($source);
imagejpeg($image, $destination, $quality);
break;
case «image/gif»:
$image = imagecreatefromgif($source);
imagegif($image, $destination, $quality);
break;
case «image/png»:
$image = imagecreatefrompng($source);
imagepng($image, $destination, $quality);
break;
}
}
compressImage(‘source.png’, ‘destination.png’, 85);

Спрайт

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

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

Наприклад, Twitter Bootstrap при завантаженні головної сторінки використовує спрайт для своїх внутрішніх іконок:

Активні веб-елементи - Поради щодо оптимізації структури та продуктивності

Тоді через CSS ви можете прописати приблизно ось такий код, щоб вивести ту частину спрайту, що вам потрібна:

.icon-edit {
background-image: url(«../img/glyphicons-halflings-white.png»);
background-position: -96px -72px;
}

Кешування

Механізм кешування браузера теж стане вам у нагоді. Так, іноді в процесі роботи це може призвести до деяких дуже смішним ситуацій, але це дійсно допомагає збільшити ефективність сайту. Кожен браузер кешує контент, наприклад, зображення, JavaScript або CSS.

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

$expire = 60 * 60 * 24 * 1;// секунд, хвилин, годин, days
header(‘Cache-Control: maxage=’.$expire);
header(‘Expires: ‘.gmdate(‘D, d M Y H:i:s’, time() + $expire).’ GMT’);
header(‘Last-Modified: ‘.gmdate(‘D, d M Y H:i:s’).’ GMT’);

Попередня вибірка

HTML5 розвивається кожен день. У ньому є одна корисна особливість, яка називається попередня вибірка. З її допомогою браузеру повідомляється, що в найближчому майбутньому, вам будуть потрібні деякі ресурси, і він повинен завантажити інформацію з них зараз – на майбутнє. Наприклад:

Схеми URI — даних / Вбудовані картинки

Пару років тому переді мною була поставлена задача розробити просту веб-сторінку, яка б складалася лише з одного файлу HTML.

І, звичайно, потрібно було вбудувати в код декілька зображень. Схеми URI — даних допомогли мені вирішити цю проблему. Ідея полягала в тому, щоб конвертувати зображення в кодуванні Base64 і помістити його в атрибут SRC тега IMG .

Наприклад:

Активні веб-елементи - Поради щодо оптимізації структури та продуктивності

З допомогою цього методу ваше зображення на самому справі буде частиною HTML-коду, і вся сторінка буде завантажуватися за один HTTP-запит. Звичайно, якщо у вас велике зображення, рядок коду буде дуже довгою. Ось приклад скрипту PHP , який перетворює зображення в рядок коду base64:

$picture = fread($fp,filesize($file));
fclose($fp);
// base64 переводить дані в двійковий код, а потім розбиває його на частини
// відповідно правилами семантики RFC 2045
$base64 = base64_encode($picture);
$tag = ‘Активні веб-елементи - Поради щодо оптимізації структури та продуктивності‘;
$css = ‘url(data:image/jpg;base64,’.str_replace(«n», «», $base64).’); ‘;

В деяких випадках це може бути корисним для вас, але майте на увазі, що IE не дуже добре обробляє такі коди.

CSS

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

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

Всі ми знаємо, що використання оператора @import не дуже хороша ідея. Тому що кожний новий оператор @import означає новий запит до сервера. І якщо у вас, наприклад, є 20 різних файлів CSS, то це означає, що браузер буде виконувати 20 HTTP-запитів.

І браузер не зможе завантажити/вивести сторінку, перш ніж не будуть завантажені всі стилі. Якщо деякі з ваших файлів CSS видалені або мають великий розмір, то перш ніж ви побачите сторінку на екрані може пройти великий час.

Використовуйте CSS-препроцессоры

За допомогою CSS-препроцесорів можна вирішити всі описані вище проблеми. Ви можете розділяти ваші стилі з різних файлів, але в кінцевому підсумку препроцесор компілює їх в один CSS-файл. Крім того, CSS-препроцессоры надають ще багато дійсно цікавих функцій: змінні, вкладені блоки, Mixins і спадкування.

Код ще видається у форматі CSS, але тепер він вже добре відформатований і структурований. Є кілька поширених препроцесорів, які ви можете спробувати застосувати на своєму сайті: Sass, LESS та Stylus. Ось простий приклад коду CSS-препроцесора LESS:

.position(@top: 0, @left: 0) {
position: absolute;
top: @top;
left: @left;
text-align: left;
font-size: 24px;
}
.header {
.position(20px, 30px);
.tips {
.position(10px, -20px);
}
.logo {
.position(10px, 20px);
}
}

В кінцевому підсумку воно призводить до наступної угруповання стилів:

.header {
position: absolute;
top: 20px;
left: 30px;
text-align: left;
font-size: 24px;
}
.header .tips {
position: absolute;
top: 10px;
left: -20px;
text-align: left;
font-size: 24px;
}
.header .logo {
position: absolute;
top: 10px;
left: 20px;
text-align: left;
font-size: 24px;
}

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

.button {
border: 1px solid #000;
padding: 10px;
background: #9f0;
color: #0029FF;
}
.active-button {
.button();
color: #FFF;
}

Ефективний CSS

Дуже часто розробники не замислюються про ефективність CSS. Ефективність CSS визначає швидкість виводу, і, якщо ваші стилі неефективні, запит буде оброблятися браузером дуже повільно. Цікаво, що браузери розбирають селектори CSS справа наліво. Це означає, що наступний код:

body ul li a {
color: #F000;
text-decoration: none;
}

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

Це означає, що елемент з ID SET буде показуватися швидше, ніж просто елемент з селектором тегів. Звичайно, немає сенсу додавати ідентифікатори до всіх елементів в дереві DOM, але ви повинні обов’язково проінспектувати свій код і поліпшити його там, де це можливо. Наприклад, якщо у вас є запис на кшталт цієї:

ul #navigation li {
background: #ff0232;
}

Ви повинні видалити частини ul, тому, що у вас на сторінці є тільки один елемент #navigation. Або в наступному селекторі:

body .content p {
font-size: 20px;
}

зрозуміло, що елемент .content є дочірнім для тега body. Насправді всі елементи є для нього дочірніми.

Ось дві корисні посилання по темі: developers.google.com і css-tricks.com

Розмір файлу

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

Об’єднуйте схожі стилі:

.header {
font-size: 24px;
}
.content {
font-size: 24px;
}

можна перетворити у:

.header, .content {
font-size: 24px;
}

Використовуйте скорочення. Замість:

.header {
background-color: #999999;
background-image: url(../images/header.jpg);
background-position: top right;
}

Можна написати наступний код:

.header {
background: #999 url(../images/header.jpg) top right;
}

Мінімізуйте ваш CSS-код. Ви можете зробити це за допомогою інструментів, які призначені для видалення зайвих пробілів і рядків. Наприклад, CSSOptimiser або Minifycss.

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

Розміщуйте посилання на ваші файли CSS між тегами .

Буде корисно включити посилання на ваші CSS-файли між тегами . В цьому випадку браузер буде завантажувати їх першими.

JavaScript

Зменшення кількості HTTP-запитів

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

Мінімізувати код

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

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

Спробуйте CommonJS, AMD, RequireJS

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

Ось приклад одного з них, взятий з http://requirejs.org/:

My Project Sample

My Project Sample

Всередині скрипта main.js ви можете прописати функцію require() для завантаження будь-якого іншого скрипту, який вам потрібен:

require([«helper/util»], function(util) {
//This function is called when scripts/helper/util.js is loaded.
//If util.js calls define(), then this function is not until fired
//util’s dependencies have loaded, and the util argument will hold
//the module value for «helper/util».
});

Використання розділу імен

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

var model = function() { … };
var view = function() { … };
var controller = function() { … };

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

ar MyAwesomeFramework = {
model: function() { … },
view: function() { … },
controller: function() { … }

Використовуйте шаблони дизайну

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

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

Шаблон конструктора

Цей шаблон можна використовувати для створення об’єкта певного типу. Наприклад:

var Class = function(param1, param2) {
this.var1 = param1;
this.var2 = param2;
}
Class.prototype = {
method:function() {
alert(this.var1 + «/» + this.var2);
}
};

Або ось:

function Class(param1, param2) {
this.var1 = param1;
this.var2 = param2;
this.method = function() {
alert(param1 + «/» + param2);
};
};
var instance = new Class(«value1», «value2»);

Шаблон модуля

Шаблон модуля дає нам можливість створювати приватні та публічні методи. Наприклад, у наведеному нижче коді, мінлива _index і метод privateMethod є приватними. А increment і getIndex – публічні:

var Module = (function() {
var _index = 0;
var privateMethod = function() {
return _index * 10;
}
return {
increment: function() {
_index += 1;
},
getIndex: function() {
return _index;
}
};
})();

Шаблон спостереження

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

Як тільки відбувається якась дія, об’єкт повідомляє про це спостерігачів. У наведеному нижче прикладі показано, як ми можемо додати спостерігача до об’єкту користувачів:

var Users = {
list: [],
listeners: {},
add: function(name) {
this.list.push({name: name});
this.dispatch(«user-added»);
},
on: function(eventName, listener) {
if(!this.listeners[eventName]) this.listeners[eventName] = [];
this.listeners[eventName].push(listener);
},
dispatch: function(eventName) {
if(this.listeners[eventName]) {
for(var i=0; i<this.listeners[eventName].length; i++) {
this.listeners[eventName][i](this);
}
}
},
numOfAddedUsers: function() {
return this.list.length;
}
}
Users.on(«user-added», function() {
alert(Users.numOfAddedUsers());
});
Users.add(«Krasimir»);
Users.add(«Tsonev»);

Шаблон ланцюжка функцій

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

var User = {
profile: {},
name: function(value) {
this.profile.name = value;
return this;
},
job: function(value) {
this.profile.job = value;
return this;
},
getProfile: function() {
return this.profile;
}
};
var profile = User.name(«Krasimir Tsonev»).job(«web developer»).getProfile();
console.log(profile);

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

Assets-Pack

Тепер, коли ми наближаємося до кінця даній статті я хочу поділитися з вами деякими своїми міркуваннями з приводу управління кодами CSS і JavaScript на сервері. Це поширений метод для забезпечення об’єднання, мінімізації та компіляції логіки додатків.

Часто якісь його елементи виконуються під час кешування, але всі операції відбуваються безпосередньо під час виконання крипта. Таким чином, перевіряється логіка коду, за допомогою якого здійснюється обробка запиту JS або CSS файлів. Під час цього процесу і здійснюється компіляція, мінімізація та упорядкування елементів структури вашого сайту.

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

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

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

Нижче наводиться опис установки і використання assets-pack.

Установка

Цей інструмент являє собою модуль NodeJS, тому перш, ніж переходити до його встановлення, у вас вже повинен бути встановлений Node. В іншому випадку просто перейдіть за адресою nodejs.org/download, де можна скачати і встановити на вашу операційну систему даний пакет. Після чого:

npm install -g assetspack

Використання

Модуль працює в конфігурації JSON. Якщо ви запускаєте його з командного рядка, то повинні заздалегідь подбати про те, щоб всі установки були прописані у файлі JSON. Набираємо в режимі емуляції роботи командного рядка наступні команди:

Створюємо файл assets.json і запускаємо в тому ж каталозі на виконання наступну команду:

assetspack —config [path to json file]

Код:

var AssetsPack = require(«assetspack»);
var config = [
{
type: «css»,
watch: [«css/src’],
output: «tests/packed/styles.css»,
minify: true,
exclude: [«custom.css»]
}
];
var pack = new AssetsPack(config, function() {
console.log(«AssetsPack is watching»);
});
pack.onPack(function() {
console.log(«AssetsPack did the job»);
});

Налаштування:

Налаштування повинні задаватися у чинному файлі / об’єкті JSON. Який являє собою просто масив об’єктів:

[
(asset object),
(asset object),
(asset object),

]

Об’єкт елемента

Базова структура об’єкта елемента виглядає наступним чином:

{
type: (file type /string, це може бути css, js або, приміром, less),
watch: (директорія або директорії перегляду/string or array of strings/),
pack: (директорія або директорії коду на виході/string or array of strings/. ),
output: шлях до отриманого файлу/string/),
minify: /boolean/,
exclude: масив імен файлів)
}

Задавати параметри опції pack не обов’язково. За замовчуванням інструмент налаштований так, щоб мінімізувати загальний розмір. Ось кілька прикладів налаштувань:

Оптимізація CSS:

{
type: «css»,
watch: [«tests/data/css», «tests/data/css2»],
pack: [«tests/data/css», «tests/data/css2»],
output: «tests/packed/styles.css»,
minify: true,
exclude: [«header.css»]

Оптимізація JavaScript:

{
type: «js»,
watch: «tests/data/js»,
pack: [«tests/data/js»],
output: «tests/packed/scripts.js»,
minify: true,
exclude: [«A. js»]
}

Оптимізація .less файлів

Оптимізація .less файлів здійснюється трохи по-іншому. Тут вже обов’язково задавати параметри опції pack, в якості яких, як правило, виступають точки входу. Ви повинні будете імпортувати всі існуючі .less файли. Виключені опції не будуть доступні для обробки.

{
type: «less»,
watch: [«tests/data/less»],
pack: «tests/data/less/index.less»,
output: «tests/packed/styles-less.css»,
minify: true
}

Якщо у вас виникнуть якісь проблеми, будь ласка, перевірте файл tests/packing-less.spec.js через спеціальний сервіс на GitHub.

Оптимізація файлів інших форматів

assets-pack може обробляти файли будь-якого формату. Наприклад, ми можемо об’єднати кілька шаблонів HTML в один файл. Для цього потрібно задати налаштування приблизно таким чином:

{
type: «html»,
watch: [«tests/data/tpl»],
output: «tests/packed/template.html»,
exclude: [«admin.html»]
}

Однак ви повинні враховувати, що в цьому випадку мінімізація коду виконуватися не буде.

Висновок

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

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

Переклад статті «Web Assets – Tips for Better Organization and Performance» був підготовлений дружною командою проекту Сайтостроение від А до Я.