Руководство по оптимизации сайта и производительности

Первые впечатления дают нам понять стоит ли наше время и усилия иметь с чем-то дело. Когда заходите на сайт, который тут же выплёвывает всплывающее окно, как только вы туда заходите, то он не только раздражает, но и создаёт негативное впечатление и не хочется снова туда возвращаться.

Когда дело доходит до веб-производительности, то пользователям не нравится ждать, поэтому очень важно «отшлифовать» ваш сайт и максимально ускорить веб-страницы. Что же определяет эту «скорость страницы»? Это следующие параметры:

  • поиск DNS
  • SSL связь (если применимо)
  • HTTP ответ
  • поиск DOM
  • HTML отрисовка
  • CSS отрисовка
  • События JavaScript

Из каждого элемента складывается общее время, потраченное на получение, визуализацию и выполнение кода, в целом это всё время от момента нажатия клавиши ввода в адресной строке до появления страницы в веб-браузере.

Имеет ли производительность значение?

Конечно да! Когда сайт загружается 5 секунд, то это очень раздражает. Создатели крупных торговых площадок борятся за миллисекунды, которые выражаются в потерях миллионов покупателей и долларов. Если ваш сайт загружается больше 5 секунд, то больше половины пользователей просто закроют его, не дожидаясь конца загрузки.
Давайте разберёмся, что можно и нужно делать для повышения производительности сайта!

Общие рекомендации

Не злоупотребляйте плагинами

Плагины отличный вариант, когда вы используете CMS! Они помогают с аналитикой, поисковой оптимизации, темами и кучей других интересных вещей, но у них есть и обратная сторона.

Чем больше плагинов у вас, тем медленнее ваш сайт, особенно с плохо написанным кодом или плагины с серверной частью, могут вызвать проблемы с безопасностью и падение сайта.

Всё на вашем сайте должно иметь функцию, поэтому ищите легкие и качественные плагины, которые будут выполнять какую-то работу и удалите все плагины, которые ничего не делают.

Не перегружайте визуально плагинами сайт, мало того, что он будет загружатся медленно, так и будет выглядеть как новогодняя ёлка.

Минимизация HTTP запросов

HTTP запросы — это словно интернет рукопожатия, они просят выдать данные и принимают их, так что чем больше запросов, тем больше времени для отрисовки страницы.

Общие советы по снижению HTTP запросов:

  • Объединяйте стили и скрипты для уменьшения количества файлов
  • Используйте вместо CSS изображений, когда это возможно
  • Комбинируйте встроенные изображения в ваши стили, чтобы избежать увеличения размеров страниц
  • Используйте кэширование браузера.

Минификация данных

Код каждой веб-страницы структурирован и с отступами для лучшего чтения, но это влияет на размер страницы и на время загрузки, для браузера же всё равно какие отступы у кода — важен лишь сам код.

Поэтому перед выдачей кода полезно минифицировать HTML, CSS и JavaScript, когда это возможно.

Уменьшение редиректов

Редиректы (перенаправления) вызывают дополнительные HTTP запросы и добавляют общее время загрузки. Например, сайты с мобильной версией направляют пользователей с десктоп-версии на мобильную, что выливается в виде медленной загрузки объектов. В этом случае лучшим решением был бы отзывчивый сайт, без каких-либо редиректов.

В конечном счете все сводится к сокращению количества переадресаций, так что вы должны меньше активов вызывать из разных мест.

Изображения

Выбор правильного формата файла

Изображения могут занимать много времени для загрузки.

Средний размер веб-страниц возрос с 702 кБайт в 2010, до 1042 кБайта в 2012 и прогнозируется в 2344 кБайта в 2015 году. И большинство от этого объёма занимает изображения.

В изображениях следует учесть их формат, так как изображения часто содержат данные, которые не используются в веб. Например, JPEG имеет Exif метаданные из камеры — дату, модель и место, всё это не используется в браузере и абсолютно бесполезно.

Наиболее распространенные форматы файлов:

  • PNG (Portable Network Graphics)
  • TIFF (Tagged Image File Format)
  • JPEG/JFIF (Joint Photographic Experts Group File Interchange Format)
  • GIF (Graphic Interchange Format)

Для большинства сайтов PNG велики, как это сжатие без потерь, формат, который используется для иллюстраций, текста, графики и логотипов. JPG не предлагают сжатие без потерь, поэтому они должны использоваться только для фотографий.

Сжатие изображений

Есть 2 типа сжатия: без потерь (не ухудшение качества) и с потерями (ухудшение качества). Лучше использовать первый при сжатии изображений, но иногда из-за формата файла вы потеряете в оптимизации. Такое может произойти при JPEG, сжатие которого вызовет потери в оптимизации, так как формат не предусматривает сжатие без потерь.

Вот некоторые полезные инструменты для сжатия изображений:

Онлайн

Десктопные

Не масштабируйте изображения в разметке

Определяйте ширину и высоту вашего изображения в коде, чтобы браузер не перерисовывал и перекомпоновывал, например:

<img width="100" height="100" src="logo.jpg" alt="Logo">

В таком случае отправляется полное изображение и сокращается время загрузки.

Использование иконочных шрифтов

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

Иконочные шрифты могут быть в любом из форматов: SVG, EPS, AI, PSD, PDF, а также CSS спрайты, однако браузеры захватывают первый формат файла и игнорируют все остальные, так что лучше выбрать один формат такой, как SVG при построении иконочного шрифта.

Пользователи могут сделать свой собственный иконочный шрифт с помощью:

В качестве альтернативы сделать это самостоятельно, следуя этому руководству по созданию SVG иконочного шрифта .

Данные URI

Данные URI — это техника встраивания содержимого, например, изображений в CSS, так что они отправляются в одном запросе HTTP, а не в нескольких, например здесь:

.icon-foobar {
    background-image: url('foo.png');
}

потребуется два запроса: один для файла CSS, а другой для изображения, в то время с помощью URI метода, нужен один будет запрос:

.icon-foobar {
    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII%3D');
}

Тем не менее, не используйте этот метод, если вы не сжимаете gzip’ом ваш HTML / CSS в HTTP, как над головой размер может быть значительно больше.

HTML

Стили сверху, скрипты снизу

Стили — это структура любой веб-страницы, без него сайты будут как из 1990-года, поэтому разместить CSS нужно в верхней части вашего кода. Таким образом страница отображается быстро и выглядит она лучше.

<head>
<meta charset="UTF-8">
<title>CDNify</title>
<!-- CSS goes here -->
<link rel="stylesheet" href=”style.css" media="all">
</head>

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

<body>
<p>Ускоряем всё до 1й космической!</p>
 <!-- JavaScript -->
<script src="script.js"></script>
</body>

Не встраивать или включайте код

Вы можете включать CSS или JavaScript в страницы с помощью 3 различных методов:

  • Inline — в строках: CSS определяется внутри атрибута стиля и JavaScript внутри атрибута OnClick.
  • Embedded — встроенный: CSS определяется внутри тега <style> и JavaScript внутри тегов <script>.
  • External — внешний: CSS загружается из тегов <link> и JavaScript из атрибутов src <script> тегов.

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

Используйте асинхронный подход

Когда задана загрузка скрипта, то браузер ждёт, пока скрипт полностью не загрузится, парсится и выполняется, перед рендерингом и всё это время пользователь ждёт.

<script src="script.js"></script>

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

<script async src="script.js"></script>

CSS

Объединение нескольких файлов CSS

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

<link rel="stylesheet" href="structure.css" media="all">
<link rel="stylesheet" href="campaign.css" media="all">
<link rel="stylesheet" href="layout.css" media="all">

Это порождает множество запросов HTTP для каждого файла стилей. Для уменьшения количества запросов нужно объединить все стили в один CSS файл.

<link rel="stylesheet" href="main.css" media="all">

Этот процесс можно автоматизировать с помощью системы сборки.

Автоматизированная система сборки

Фронтэнд система сборки — это способ автоматизации задач, таких как минификация файлов, оптимизация изображений, компиляция CSS и объединения кода в один файл.

Есть много автоматизированных инструментов, которые можно использовать:

  • Gulp : Потоковая система сборки
  • Grunt : Система сборки построенная на задачах
  • Bower : Управление фронтэнд пакетами
  • Yeoman: Клиентский стек

Использование <link> вместо @import

Вы можете подключать внешние стили двумя способами, используя тег <link>:

<link rel="stylesheet" href="style.css">

или директиву @import:

@import url('style.css');

@import не позволяет браузеру загрузить активы в то же время, так что лучше использовать <link>.

Минимизация вашего CSS

Код должен быть легкочитаемым и в поддерживаем с использованием соответствующей структуры: отступов и комментариев, которые объясняют, что происходит.

/* --- Nav Bar --- */

.header {
  height: 350px;
  width: 950px;
  margin: 0 auto;
}

/* --- Footer --- */

.footer {
  height: 450px;
  width: 950px;
  margin: 0 auto;
}

Однако браузерам всё равно, поэтому нужно сжать код для уменьшения размера файла.

.header{height: 350px;width: 950px;margin: 0 auto;}.footer{height: 450px;width: 950px;margin:0 auto;}

JavaScript

Избегайте DOM манипуляций

Доступ к DOM является времязатратным, так как требует манипуляций кода, захотите вы, например, обновить:

<div id="container"></div>

некоторым JavaScript:

<script>
  var container = document.getElementById("container");
  container.innerHTML = "Foo Bar";
</script>

результат будет выглядеть так:

<div id="container">Foo Bar</div>

Попробуйте оптимизировать DOM манипуляции так, чтобы вам не нужно было давать браузеру больше кода для отрисовки. Например, если вы запрашиваете DOM через цикл, сделайте это один раз и храните результат в переменной, таким образом, вам не нужно будет обращаться к DOM и замедлять браузер.

Минимизация перерисовки и перекомпоновки

Перерисовка и перекомпоновка осуществляются при внесении изменений в DOM, заставляя его рендерится повторно, например, при изменении элемента происходит перерисовка и при изменении макета страницы запускается перекомпоновка.

Установка толщины к стилю, как style.width, будет заставить браузер думать что в макет будет внесены изменения и в конечном итоге замедлить его работу. Если вам нужно внести изменения подобные этому, тогда сделайте это один раз. таким образом браузеру не нужно будет перерендеривать объекты.

Используйте содержимое 3-х сторон асинхронно

Когда дело доходит содержания 3-х сторон, то не всегда оно упаковано надлежащим образом, иногда оно может быть просто абы как, как результат — торможение ваших страниц или ещё хуже это содержимое хостится на серверах 3-х сторон заблокированное для соединений ваших пользователей.

Лучше всего всегда загружать содержимое 3-х сторон асинхронно, таким образом вся страница не замедлится для краулеров или не будет заблокирована.

var script = document.createElement('script'),
scripts = document.getElementsByTagName('script')[0];
script.async = true;
script.src = url;
scripts.parentNode.insertBefore(script, scripts);

Если у вас есть несколько сценариев, которые вы хотите нагрузку асинхронно затем использовать:

(function() {
    var script,
    scripts = document.getElementsByTagName('script')[0];
    function load(url) {
        script = document.createElement('script');
        script.async = true;
        script.src = url;
        scripts.parentNode.insertBefore(script, scripts);
    }
    load('//apis.google.com/js/plusone.js');
    load('//platform.twitter.com/widgets.js');
    load('//s.thirdpartywidget.com/widget.js');
}());

Длины кэш массива

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

var loopArray = new Array(100),
    len, i;

    for (i = 0; i < loopArray; i++) {
      // :( - Array size is recalculated 100 times
    }

    for (i = 0, len = loopArray.length; i < len; i++) {
      // :) - Array size is calculated once and then stored in cache
    }

Бросайте document.write

Давайте здесь определимся: document.write — это плохая практика! Это зависимость к странице, которая заставляет переписывать весь контент, однако она по-прежнему необходима как синхронная запаска для некоторых JavaScript файлов, поэтому по возможности постарайтесь избегать это выражение.

Например, следующий покажет «world!», а не «hello world!», так как он выполняется после того, как содержимое загружено с помощью события window.onload.

<span>hello </span>
<script>
  window.onload = function() {
    document.write('<span>world!</span>');
  };
</script>

По возможности, старайтесь избегать document.write вообще, используя какой-нибудь другой метод.

Минимизируйте ваш JavaScript

CSS код — не единственный, который должен быть минимизирован, ещё у нас есть JavaScript с громоздкой структурой и комментариями, которые могут сильно раздувать размер файла, например:

MyJavaScript.app = function() {

  var foo = true;

  return {
    bar: function() {
      // stuff happens
    }
  };

};

Когда дело доходит до структуры и комментариев. то браузеру все равно, так как он обрабатывает и предоставляет код независимо. Минификация кода уменьшает размер файла, что в свою очередь улучшает скачку, парсинг и выполнение одновременно.

MyJavaScript.app=function(){var a=!0;return{bar:function(){}}}

Объединяйте несколько файлов JavaScript

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

<script src="navbar.js"></script>
<script src="component.js"></script>
<script src="page.js"></script>
<script src="framework.js"></script>
<script src="plugin.js"></script>

Тем не менее, нас такой метод не устраивает. так как его недостатком является множество запросов HTTP для каждого файла. Вместо этого, объедините JavaScript в меньшее количество файлов, чтобы уменьшить количество запросов.

<script src="main.js"></script>

В качестве альтернативы, можно объединить их в один файл и автоматизировать этот процесс, используя систему сборки.

JQuery

Используйте последнюю версию JQuery

Код 3-х сторон, например, JQuery всегда поддерживается в актуальном состоянии для исправления ошибок, добавления новых функций, улучшения читаемости и оптимизации алгоритмов, так что нужно брать последнюю версию.

Всегда берите последнюю версию, используя:

https://code.jquery.com/jquery-latest.js

Однако могут появлятся конфликты между последней версии и вашим кодом, если так происходит, то вот ссылка на последнюю стабильную версию:

https://code.jquery.com/jquery-1.11.1.min.js

Селекторы

Есть много разных способов, чтобы взять элемент из DOM, такие как классы, идентификаторы или использование методов, таких как find() и children(), однако наиболее эффективный способ — это использовать селекторы, так как он основан на нативной DOM операции:

$("#selector");

Когда дело доходит до DOM всегда пытайтесь оптимизировать захват данных, так как «ныряние» в DOM каждый раз отнимает много времени.

Подводные камни jQuery производительности

JQuery это библиотека JavaScript, предназначенная для упрощения кодирования сценариев на стороне клиента в HTML, но за всё нужно платить. Библиотеки, как правило, работают медленнее, так как они работают вместе с программой, а родной JavaScript обычно быстрее, чем JQuery, поэтому вместо того, чтобы использовать что-то вроде jQuery.each, нужно использовать родной метод JavaScript для цикла:

for ( var i = 0, len = a.length; i < len; i++ ) {
    e = a[i];
}

Когда дело доходит до принятия решения, что выбрать, JQuery или JavaScript, подумайте, чем бы вы могли пожертвовать: простотой использования или производительностью.

Оригинал - статья A Guide to Optimising Website & Application Performance