Як я зробив найшвидший сайт в Таїланді

image
Передмова
Зайнятися цим проектом і написати цю статтю, надихнув мене "молодий і жартівливий чоловік який прискорював сторінку з reactjs". Якщо хтось пам'ятає гучну свого часу статтю від сайту pingdom.com про те, що "Сторінки в інтернеті пристойно обросли жиром" їх висновок складався до того, що раніше до ваги сторінки в основному додавали зображення, тепер до цього "жиру" накинули і JavaScript. Сторінка жартівливого молодої людини не дає особливої практичної користі — більше розминка для мізків. Я ж вирішив допомогти своїй дівчині з продажем самого популярного продукту з її асортименту.

Я вже й раніше намагався робити вкрай мінімалістичні сайти. Такі проекти були викликані бажанням вийти за рамки фреймворків і можливо закінчити проект швидше. Такий підхід досить популярний і серед моїх друзів — популярність KISS (Keep It Simple, Stupid) дає свої плоди. Будучи в основному бекенд програмістом — я багато часу проводжу з оптимізацією коду на стороні сервера. На практиці зрозумів, як це важливо не робити такі зміни наосліп, а підкріплювати їх метрикою.
Підготовка
Фронт-енд фреймворк
Я не фронтенд програміст, мені доводиться покладатися на фронтенд фреймворки. Найчастіше це означає bootstrap з усім "його добром". І хоча bootstrap компоненти можна використовувати селективно, це все одно означає що я притягну з собою jQuery. Я бачив вже досить native-javascript бібліотек, які працюють без Jquery. Розмір бутстрапа і його компонент теж мене не влаштовував, мені завжди здавалося, що він "стилізує" трохи більше, ніж потрібно.
Тому трохи погугливши трохи, я знайшов фреймворки які позиціонують себе як минималистычные. Ось приблизний список того, що я розглядав
Я вибрав фрейворк base. Більшість з причин глибокого особисті:
  1. Я вже працював з більш раней версією
  2. Мені здавалося що javascript компоненти мені не потрібні, а якщо потрібні, то я б хотів їх вибрати сам. Base — чисто css фреймворк.
  3. Використовує gulp як білд тул. Про яке я чув багато хорошого, деякі умільці навіть намагалися його інтегрувати в рейці (з якою я часто маю справу).
  4. Я знайшов темплейт від автора фреймворку який підходив для моєї мети. Я якщо чесно не хотів багато возитися з версткою, мета цього проекту була інша. Тому я із задоволенням віддав кілька доларів автору за це.
Тому я не буду рекомендувати тільки Base, а видав список. Але я повинен обмовитися, що можна почати ще більш мінімалістично, тільки з grid system — sussy grid, наприклад.
Хостинг
Я не збирався робити динамічний контент. І хоч здавалося б логічним зробити форму для покупки, більшість тайських магазинів що я бачив уникали цього. Форма для покупки ще ускладнюється тим, що їх довелося б інтегрувати з банками, а в Таїланді немає чітких лідерів у банківській сфері. Їх більше 10 і всі вони більш або менш користуються попитом, навіть серед моїх друзів іноземців\тайців вибір банку вкрай різниться. Дуже багато покупок робиться через інтернет банки і месенджер line. Тому я вирішив не ламати звичних патернів, тим більше це вкрай спрощує моє завдання.
Мені потрібен хостинг тільки для статичного контенту. Самим популярним вибором тут є github pages і AWS. Я побоявся використати github pages з-за обмежень по трафіку, а AWS мені здався не найдешевшим рішенням (за моїми вкрай грубими оцінками близько 4 баксів в місяць). У мене вже було три сайту, які крутяться на nearlyfreespeech.net — і десять баксів вистачило на них щоб вони працювали більше року. Дешевше не завжди означає краще, але в цьому випадку я вже мав досвід і ніяких нарікань у мене немає.
image
Важлива поправочка
_ В коментарях відзначили, що мій географічний вибір сервера не самий розумний для Тайського сайту. Так само, якою б легковагий не був apache — він все одно створює новий потік для кожного з'єднання.
Метрика
Я спочатку домовився сам з собою, що я не буду покладатися на власні "відчуття". А буду покладатися на суспільно визнаний інструментарій.
gtmetrix.com — Я вибрав як основний тул для вимірювання "швидкості" мого сайту. Він включав в себе два найпопулярніших інструменту google page speed і yslow. Виявилося, що оригінальний page speed все таки знайшов трохи більше помилок. Це привело мене до висновку, що покладатися на 100 відсотковий показник у gtmetrix і схожі тули — можливо, не найкраща ідея, це ж скриптованая перевірка на "найпопулярніші" помилки. Ви завжди можете піти далі.
Вимірювати як швидко сайт буде відкриватися під навантаженням я не збирався. Тому можливі проблеми з продуктивністю у Apache я ігнорував. Але вам, можливо, варто задуматися.
Оптимізація
Gzip
найпростіша оптимізація яку можна було зробити — це надавати статичні файли у форматі gzip. Це я робив у всіх проектах в яких я працював до цього. Тому вкрай швидко накидав таск в gulpfile.js щоб автоматизувати процес створення .gz файлів.
var gzip = require('gulp-gzip');

gulp.task('gzip', function (){
return gulp.src('./public//**/*.+(js|css|html)')
.pipe(gzip())
.pipe(gulp.dest('./public/'))
});

І так само швидко накидав .htaccess файл, який підсовує браузеру архивированный файл.
Header add Vary accept-encoding
RewriteEngine on
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*)$ $1.gz [L]

Мені так само довелося копіювати файл в білд папочку, без особливих змін. Це виявилося ще простіше:
gulp.task('htaccess', function () {
return gulp.src('./src/**/.htaccess')
.pipe(gulp.dest('./public/'));
});

Так само, довелося оновити і build таск
gulp.task('build', function() {
runSequence('clean', 'sass', 'build-img', 'jsmin', 'inlinesource', 'htaccess', 'gzip');
});

Помоєму це найпростіший спосіб оптимізувати сторінку, тільки ледачий не робить це в своїх проектах. У багатьох сучасних движках це все доводиться до банальщини — додати плагін або включити опцію.
Кешування
Менш тривіальної виявилася завдання по указыванию заголовків для кешування. З AWS ці вже автоматизовано. Я намагався пригадати коли я це робив останній раз, але так і не згадав коли. Тому з допомогою магічної сили гугла, пару спроб я все-таки зробив щось 100% приеемлемое для gtmetrix.
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType text/javascript "access plus 2 month"
ExpiresByType application/javascript "access plus 2 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType image/icon "access plus 1 year"
ExpiresByType application/ico "access plus 12 month"
ExpiresDefault "access plus 2 days"
</IfModule>

Але щоб уникнути двох спроб, я б рекомендував скористатися темплейтом для сервера з проекту html5-boilerplate. Я в наступний раз обов'язково це зроблю :)
Зображення
Для людини у якої немає Photoshop a на комп'ютері — робота з зображеннями це велика попаболь. Половина проблем з изображениеми було вирішено за мене, за рахунок того що я вибрав готовий темплейт — мені не довелося возитися з спрайтами, векторами. Але це не вирішило всіх моїх проблем — мені потрібні були інші іконки та інші зображення.

Правильний вибір формату для зображень

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

Компресія без втрат

Як людина з інженерною освітою, я знаю ціну спеціалізованим інструментів. Вони дуже часто полегшують роботу більше ніж one-fits all інструмент. Можна програмувати на notepad'e, але частіше стає нашим основним робочим інструментом — sublime text, rubymine. В даному випадку imageoptim хороший, але не достатньо хороший. Так як у мене було багато jpeg файлів, я знайшов порівняльний аналіз лослесс стиснень — виграв jpegtran.
у gulp це виявилося дуже просто:
var jpegtran = require('imagemin-jpegtran');

gulp.task('build-jpg', function () {
gulp.src('./src/img/*.+(jpg|jpeg)')
.pipe(jpegtran({ progressive: true })())
.pipe(gulp.dest('./public/img'));
});

Граємося з оптимізацією квітів в jpeg

Але вибором лише правильного формату все не закінчилося. Зображення все-одно були надто великі. Мій hero background займав більше половини мегабайта.
image

У мене немає photoshop a, а що без нього тут робити я не дуже розумів. Але друзі посприяли і порадили відмінний проект TinyJpg — все виявилося дуже просто.
CSS
Я все таки вирішив заинлайнить css. Це трохи контринтуитивно, люди радять тримати все це в окремому файлі щоб стилі могли закэшироваться. Є навіть ймовірність, що у юзера вже закешировано все це, особливо якщо використовуєш популярний фреймворк.
Я скоріше так би і зробив, якщо б використав bootstrap. Але так як я використав менш розповсюджений base і не дуже очікував що користувачі будуть повертатися на мій сайт — то я вирішив видалити зайвий http запит.
У gulp це виявилося як завжди простіше всього:
<link rel="stylesheet" href="css/styles.css" inline>

Fonts
Цікава і несподівана ситуація для мене склалося з Google Fonts, в темплейте було використано два різних фонта. І начебто навіть розумно оптимізовані:
  1. Вони завантажувалися за один запит http
  2. Використовував WebFontLoader, який асинхронно завантажував фонти і рендерил сторінку після завантаження.
Але gtmetrix продовжував лаятися на фонти — у них не було cache headers. Я вирішив піти по шляху вже запропонованому у статті на яку я посилався на початку позбувся від google fonts. у всіх девайсах є цілком пристойні вбудовані фонти. Тому я залишив ось такий набір:
font-family: "Helvetica Neue", "Calibri Light", Roboto, sans-serif;

Геолокація серверів
Поки в Таїланді, я накидав швидкий скрипт для перевірки швидкості з Тайланду:
require "uri"

SERVERS = [
{
:name => "nearlyfreespeach",
:url => "http://euphorbia.soihok.com/"
},
{
:name => "AWS servers",
:url => "https://d4s21h4msr5q2.cloudfront.net/"
}
]

SERVERS.each do |server|
uri = URI.parse(server[:url])
puts "Performing HTTP speed test for #{server[:name]}"
puts `wget -O /dev/null #{server[:url]} 2>&1 | awk '/\\/dev\\/null/ {speed=\$3 \$4} END {gsub(/\\(|\\)/,"",speed); print speed}"
end

І я отримав такі результати:
$ rspec speed_test.rb
Performing HTTP speed test for nearlyfreespeach
85.1 KB/s
Performing HTTP speed test for AWS servers
203KB/s

Performing HTTP speed test for nearlyfreespeach
92.5 KB/s
Performing HTTP speed test for AWS servers
192KB/s

$ rspec speed_test.rb
Performing HTTP speed test for nearlyfreespeach
83.2 KB/s
Performing HTTP speed test for AWS servers
168KB/s

Тому не робіть моїх помилок. Вибирайте хостерів з серверами близькими до вашої цільової аудиторії. Сайти будуть відкриватися як мінімум в два рази швидше!
Висновки
Ось такий от вийшов вебсайт — http://euphorbia.soihok.com/
А ось останні метрики з gtmetrix — https://gtmetrix.com/reports/euphorbia.soihok.com/zhMn6OhU
Як стверджують багато Сеошників — швидкий сайт дає бонуси в гуглі. Я якщо чесно на це сподівався, але не перевіряв. Тому тут мені метриками крити не вийде.
Я часто подорожую і періодичний доводиться працювати з вкрай сумнівним з'єднанням — будь то мобільний з'єднання, готелі або просто не розвинений інтернет десь в Азії. І мене сильно засмучує що немає мобільних версій сайтів, що сайти навіть для десктопів не оптимізовані.
Я дуже багато фокусувався щоб робити швидкий бекенд, якому не потрібно багато ресурсів. Але я ніколи не фокусувався сильно на фронт-енде, хоча б тому що вважав що 100% показники мати не можливо. Але це виявилося, хоч і не просто, але можливо. Більш того, можна піти далі і прискорити більше "необхідного мінімуму". Всі ці принципи і досвід побудови швидких сторінок універсальні і наступні сайти прискорювати буде набагато легше і швидше! Про це лише треба почати думати, що десь там, на рівні підсвідомості! І ваші користувачі скажуть вам спасибі і будуть повертатися.
Бажаю швидких сайтів всім нам!
*"найшвидший сайт в Таїланді" — це мій "кричущий" заголовок, я не беруся це стверджувати зі 100% впевненістю. Але більшість сайтів, що я бачив в Тайланді — не найшвидші.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.