Pull to refresh

Как я сделал самый быстрый сайт в Таиланде

Reading time8 min
Views24K

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.1KB/s
Performing HTTP speed test for AWS servers
203KB/s

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

$ rspec speed_test.rb
Performing HTTP speed test for nearlyfreespeach
83.2KB/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% уверенностью. Но большинство сайтов что я видел в Тайланде — не самые быстрые.

Tags:
Hubs:
Total votes 51: ↑41 and ↓10+31
Comments53

Articles