- PVSM.RU - https://www.pvsm.ru -

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

image [1]

Предисловие

Заняться этим проектом и написать эту статью вдохновил меня "молодой и шутливый человек который ускорял страницу с reactjs [2]". Если кто-то помнит нашумевшую в своей время статью от сайта pingdom.com, о том что "Страницы в интернете прилично обросли жиром [3]" их вывод складывался к тому, что раньше к весу страницы в основном добавляли изображения, теперь к этому "жиру" накинули и JavaScript. Страница шутливого молодого человека не дает особой практической пользы — больше разминка для его мозгов. Я же решил помочь своей девушке с продажей самого популярного продукта из ее ассортимента.

Я уже и раньше пытался делать крайне минималистичные сайты [4]. Такие проекты были вызваны желаниям выйти за рамки фреймворков и возможно закончить проект быстрее. Такой подход достаточно популярен и среди моих друзей [5] — популярность KISS (Keep It Simple, Stupid) дает свои плоды. Будучи в основном бэкенд программистом — я много времени провожу с оптимизацией кода на стороне сервера. На практике понял, как это важно не делать такие изменения вслепую, а подкреплять их метрикой.

Подготовка

Фронт-енд фреймворк

Я не фронт-енд программист и поэтому мне приходится полагаться на фронт-енд фреймворки. Чаще всего это означает bootstrap со всем "его добром", и хотя bootstrap компоненты можно использовать селективно, это все равно означает что я притащу с собой как минимум jQuery. Я был не уверен что мне нужен jQuery, я видел уже достаточно native-javascript библиотек которые работают без Jquery. Размер бутстрапа и его компонент тоже меня не устраивал, мне всегда казалось что он "стилизует" чуть больше чем нужно.

Поэтому немного погуглив немного, я нашел фреймворки которые позиционируют себя как минималистычные. Вот примерный список того что я рассматривал

Я выбрал фрейворк base. Большинство из причин глубокого личные:

  1. Я уже работал с более раней версией
  2. Мне казалось что javascript компоненты мне не нужны, а если нужны, то я бы хотел их выбрать сам. Base — чисто css фреймворк.
  3. Использует gulp как билд тул. О котором я слышал много хорошего, некоторые умельцы даже пытались его интегрировать в рельсу (с которой я часто имею дело).
  4. Я нашел темплейт от автора фреймворка который подходил для моей цели. Я если честно не хотел много возиться с версткой, цель этого проекта была другая. Поэтому я с удовольствием отдал несколько долларов автору за это.

Поэтому я не буду рекомендовать только Base, а выдал список. Но я должен оговориться, что можно начать еще более минималистично, только с grid system — sussy grid, например.

Хостинг

Я не собирался делать динамический контент. И хоть казалось бы логичным сделать форму для покупки, большинство тайских магазинов что я видел избегали этого. Форма для покупки еще усложняется тем, что их бы пришлось интегрировать с банками, а в Тайланде нету четких лидеров в банковской сфере. Их больше 10 и все они более или менее пользуются спросом, даже среди моих друзей иностранцевтайцев выбор банка крайне разнится. Очень много покупок делается непосредственно через интернет банки и мессенджер line. Поэтому я решил не ломать привычных паттернов, тем более это крайне упрощает мою задачу.

Мне нужен хостинг [10] только для статического контента. Самым популярным выбором тут является github pages и AWS. Я побоялся использовать github pages из-за ограничений по трафику [11], а AWS мне показался не самым дешевым решением (по моим крайне грубым оценкам около 4 баксов в месяц). У меня уже было три сайта, которые крутятся на nearlyfreespeech.net [12] — и десяти баксов хватило на них чтобы они работали больше года. Дешевле не всегда значит лучше, но в этом случае я уже имел опыт и никаких нареканий у меня нету.

image

_ В комментариях отметили что мой географический выбор сервера не самый разумный для Тайского сайта. Так же, какой бы легковесный не был apache — он все равно создает новый поток для каждого соединения [13]. Пока я еще в Тайланде — замерю, задвину на сервер поближе и обновлю статью.

Метрика

Я изначально договорился сам с собой, что я не буду полагаться на собственные "ощущения". А буду полагаться на общественно признанный инструментарий.

gtmetrix.com — Я выбрал как основной тул для измерения "скорости" моего сайта. Он в себя включал два самых популярных инструмента google page speed и yslow. Оказалось, что оригинальный page speed [14] все таки нашел чуть больше ошибок. Это привело меня к выводу, что полагаться на 100 процентный показатель в gtmetrix и схожие тулы — возможно не самая лучшая идея, это же скриптованая проверка на "самые популярные" ошибки. Вы всегда можете пойти дальше.

Оптимизация

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 [15]. Я в следующий раз обязательно это сделаю :)

Изображения

Для человека у которого нету Photoshop'a на компьютере — работа с изображениями это большая попаболь. Половина проблем с изображениеми было решено за меня за счет того что я выбрал готовый темплейт — мне не пришлось возиться с спрайтами, векторами. Но это не решило всех моих проблем — мне нужны были другие иконки и другие изображения.

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

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

Больше ликбеза на эту тему можно найти на страницах гугла [16] (от людей которые понимают в этом больше чем я).

Компрессия без потерь

Как человек с инженерным образованием, я знаю цену специализированным инструментам. Они очень часто облегчают работу больше чем one-fits-all инструмент. Можно программировать на notepad'e, но чаще становится нашим основным рабочим инструментом — sublime text, rubymine. В данном случае imageoptim хорош, но не достаточно хорош. Так как у меня было много jpeg файлов, я нашел сравнительный анализ лослесс сжатий — выйграл jpegtran [17].

в 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 [18] — все оказалось слишком просто.

CSS

Я все таки решил заинлайнить css. Это немного контринтуитивно, люди советуют держать все это в отдельном файле чтобы стили могли закэшироваться. Есть даже вероятность, что у юзера уже закешировано все это, особенно если используешь популярный фрэймворк.

Я скорее так бы и сделал, если бы использовал bootstrap. Но так как я использовал менее распространеный base и не очень то ожидал что пользовали будут возвращаться на мой сайт — то я решил удалить лишний http запрос.

В gulp это оказалось как обычно проще всего:

<link rel="stylesheet" href="css/styles.css" inline>

Fonts

Интересная и неожиданная ситуация для меня сложилось с Google Fonts, в темплейте было использовано два разных фонта. И вроде даже разумно оптимизированы:

  1. Они загружались за один http запрос
  2. Использовал WebFontLoader [19], который асинхронно загружал фонты и рендерил страницу после загрузки.

Но gtmetrix продолжал ругаться на фонты — у них небыло cache headers. Я решил пойти по пути уже предложенному в статье на которую я ссылался в начале [2] и избавился от google fonts. во всех девайсах есть вполне приличные встроеные фонты. Поэтому я оставил вот такой вот набор:

font-family: "Helvetica Neue", "Calibri Light", Roboto, sans-serif;

Выводы

Вот такой вот получился вебсайт — http://euphorbia.soihok.com/ [20]
А вот последнии метрики с gtmetrix — https://gtmetrix.com/reports/euphorbia.soihok.com/zhMn6OhU [1]

Как утверждают многие СЕОшники — быстрый сайт дает бонусы в гугле. Я если честно на это надеялся, но не проверял. Поэтому здесь мне метриками крыть не получится.

Я часто путешествую и периодический приходится работать с крайне сомнительным соединением — будь то мобильное соединение, отели или просто не развитый интернет где то в Азии. И меня сильно расстраивает что нету мобильных версий у сайтов, что сайты даже для десктопов не оптимизированы.

Я очень много фокусировался чтобы делать быстрый бэкенд, которому не нужно много ресурсов. Но я никогда не фокусировался сильно на фронт-енде, хотя бы потому что считал что 100% показатели иметь не возможно. Но это оказалось, хоть и не просто, но возможно. Более того, можно пойти дальше и ускорить более "требуемого минимума". Все эти принципы и опыт построения быстрых страниц универсальны и последующие сайты ускорять будет гораздо легче и быстрее! Об этом лишь надо начать думать, где-то там на подсознании! И ваши пользователи скажут вам спасибо и будут возвращаться.

Желаю быстрых сайтов всем нам!

* "самый быстрый сайт в Таиланде" — это мой "кричащий" заголовок, я не берусь это утверждать со 100% уверенностью. Но большинство сайтов что я видел в Тайланде — не самые быстрые.

Автор: lunaticman

Источник [21]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/front-e-nd/235916

Ссылки в тексте:

[1] Image: https://gtmetrix.com/reports/euphorbia.soihok.com/zhMn6OhU

[2] молодой и шутливый человек который ускорял страницу с reactjs: https://hackernoon.com/10-things-i-learned-making-the-fastest-site-in-the-world-18a0e1cdf4a7#.bpdgu76it

[3] Страницы в интернете прилично обросли жиром: http://royal.pingdom.com/2011/11/21/web-pages-getting-bloated-here-is-why/

[4] минималистичные сайты: http://www.howtodigitalnomad.com/

[5] моих друзей: https://ristrettogram.com/

[6] http://getbase.org: http://getbase.org

[7] http://getskeleton.com/: http://getskeleton.com/

[8] http://fluidable.com/: http://fluidable.com/

[9] http://purecss.io/: http://purecss.io/

[10] хостинг: https://www.reg.ru/?rlink=reflink-717

[11] ограничений по трафику: https://www.quora.com/What-are-bandwidth-and-traffic-limits-for-GitHub-pages/answer/Rachel-Berry-9

[12] nearlyfreespeech.net: http://nearlyfreespeech.net/

[13] он все равно создает новый поток для каждого соединения: https://stackoverflow.com/questions/5171639/creation-of-new-process-for-each-request-of-web-page

[14] оригинальный page speed: https://developers.google.com/speed/pagespeed/insights/

[15] html5-boilerplate: https://github.com/h5bp/server-configs-apache/blob/master/dist/.htaccess

[16] на страницах гугла: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/image-optimization

[17] выйграл jpegtran: http://compression.ca/act/act-jpeg.html

[18] TinyJpg: http://tinyjpg.com

[19] WebFontLoader: https://github.com/typekit/webfontloader

[20] http://euphorbia.soihok.com/: http://euphorbia.soihok.com/

[21] Источник: https://habrahabr.ru/post/319542/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best