Руководство по оптимизации сайта и производительности
Первые впечатления дают нам понять стоит ли наше время и усилия иметь с чем-то дело. Когда заходите на сайт, который тут же выплёвывает всплывающее окно, как только вы туда заходите, то он не только раздражает, но и создаёт негативное впечатление и не хочется снова туда возвращаться.
Когда дело доходит до веб-производительности, то пользователям не нравится ждать, поэтому очень важно «отшлифовать» ваш сайт и максимально ускорить веб-страницы. Что же определяет эту «скорость страницы»? Это следующие параметры:
- поиск 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, сжатие которого вызовет потери в оптимизации, так как формат не предусматривает сжатие без потерь.
Вот некоторые полезные инструменты для сжатия изображений:
Онлайн
- Smush.it
- TinyPNG
- Kraken.io
- JPEGmini
- imagecompressor от websiteplanet (40 изображений с сохранением на Dropbox & Google drive)
Десктопные
Не масштабируйте изображения в разметке
Определяйте ширину и высоту вашего изображения в коде, чтобы браузер не перерисовывал и перекомпоновывал, например:
<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
16-11-2014 Виктор Матушевский