После выхода в свет очередного дизайнерского решения в виде навороченного сайта с большим объёмом вёрстки, js`а и прочих "рюшечек" часто встаёт вопрос о медленной загрузке страниц, даже при условии проделанной работы по оптимизации кода, структуры БД и запросов. В этом случае полезно задуматься о клиентской оптимизации (или, по-другому, — оптимизации скорости загрузки страниц на стороне клиента), в нюансах которой мы и попробуем разобраться.
Вторая часть статьи, посвященной ускорению сайта
Анализ текущих показателей скорости загрузки сайта
Для начала, следует воспользоваться средствами анализа скорости загрузки страницы, которые условно можно разделить на две категории:
- плагины для браузеров;
- сторонние сервисы.
В качестве первого варианта подойдут следующие плагины (на примере FF):
- FireBug (вкладка Сеть);
- YSlow (от Yahoo!);
- Page Speed (от Google).
Примерами средств, относящихся ко второй категории, могут служить:
- webpagetest.org;
- fpt.pingdom.com;
- developers.google.com/pagespeed/?hl=ru
- webopulsar.ru;
- webo.in.
Рассмотрим методы клиентской оптимизации на примере сайта itsoft.ru. За начальные значения возьмём отчёты:
- itsoft.ru YSlow;
- http://webopulsar.ru/reports/1/09d14946e015c7a4.html;
- .
Время загрузки страницы может варьироваться в зависимости от многих факторов. За точку отсчёта возьмём следующие значения:
Анализ доступных способов ускорения загрузки сайта
Итак, что можно сделать для ускорения процесса загрузки страницы в общем:
- выноc стилей и скриптов в подключаемые файлы, отказ от использования атрибута style, тега script;
- использование сжатия gzip/deflate для текстовой информации;
- использование pack и minify в javascript-скриптах для уменьшения размера файлов;
- использование склейки css и js файлов в один для уменьшения количества запросов;
- выбор верного формата файлов изображений, уменьшение размера изображений без потери качества;
- предоставление изображения с нужными пропорциями, вместо их изменения посредством css / html;
- использование css-спрайтов (возможно использование Image Map / Data:URI) для сокращения количества запросов к серверу для получения большого количества (необязательно) маленьких иконок-изображений;
- установка заголовков кеширования для статической информации и файлов;
- использование keep-alive соединений, при наличии на сайте динамического медиа-контента (например фотогалереи);
- использование CDN или организация нескольких доменов для распределения контента и его параллельной загрузки, в силу того, что браузеры используют порядка 2-6 одновременных соединений к одному хосту;
- заключение javascript скриптов, обращающихся к сторонним сервисам в iframe;
- вынесение подключения js-скриптов в конец файла перед закрывающим тегом body ;
- вынесение подключения стилей в начало страницы в тег head ;
- исключение ситуации с попыткой подключения недоступного контента;
- уменьшение количества соединений при загрузке страницы;
- использование/отключение ETags;
- использование/принудительное обнуление загаловка Last-Modified
- управление параметром max_connections сервера.
Оптимизация содержимого на примере сайта itsoft.ru
Перейдём к конкретным действиям, которые мы можем предпринять в данной ситуации. Начнём с сжатия и кеширования:
- использование ETags;
- использование gzip/deflate;
- использование заголовков, управляющих процессом кеширования.
Модифицированный файл .htaccess будет выглядеть следующим образом:
#naive
FileETag MTime Size
<IfModule mod_headers.c>
# 1 MONTH
<FilesMatch "\.(jpg|jpeg|gif|png|swf|css|js)$">
Header set Cache-Control "max-age=2419200, public"
</FilesMatch>
# 1 DAY
<FilesMatch "\.(html|htm|php)$">
Header set Cache-Control "max-age=86400, private, proxy-revalidate"
</FilesMatch>
</IfModule>
<IfModule mod_expires.c>
<FilesMatch "\.(jpg|jpeg|gif|png|swf|css|js)$">
ExpiresActive on
ExpiresDefault "access plus 1 month"
</FilesMatch>
<FilesMatch "\.(html|htm|php)$">
ExpiresActive on
ExpiresDefault "access plus 1 day"
</FilesMatch>
</IfModule>
<IfModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file \.(html?|txt|css|js|php|pl|xml)$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>
<Ifmodule mod_deflate.c>
AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript
</Ifmodule>
#endofnaive
Как мы видим из отчёта, полученного после проделанных манипуляций скорость загрузки страницы уменьшилась, в то время, как количество запросов при повторной загрузке страницы сократилось с 163 до 29:
В нашем случае отдельно следует настроить:
- nginx;
- увеличить max_connections для расширения возможности одновременной отдачи контента сервером.
Для сокращения количество запросов, увеличения количество одновременных загрузок, увеличения скорости загрузки и уменьшения суммарного веса страницы:
- объединить все css- и js-файлы в один;
- выстроить верный порядок подключения файлов;
- минимизировать и сжать js-код;
- вынести в подключаемый файл все css- и javascript-вставки;
- использовать CDN для javascript-библиотек.
Сервисы для сжатия и минимизации css- и js-файлов:
- http://www.refresh-sf.com/yui/
- jscompress.com
- javascriptcompressor.com/
В качестве CDN возможно использовать:
- Яндекс: http://api.yandex.ru/jslibs/ ;
- Google: http://code.google.com/apis/libraries/ .
Результаты теста загрузки страницы после проделанной работы по оптимизации:
Для сокращения количество запросов, уменьшения суммарного веса страницы и сокращения количества DOM-элементов необходимо:
- использовать CSS-Sprites для изображений;
- подогнать размеры используемых изображений под реально необходимые на сайте, для сокращения времени на их ресайзе;
- убрать лишние подключения сторонних сервисов на сайте, где это возможно.
Результаты тестирования скорости загрузки страницы после работы с изображениями и оптимизации лишних подключений:
Результаты клиентской оптимизации
После дополнительных косметических правок имеем следующие результаты:
- Page Speed: Score of 93 (out of 100);
- YSlow: Overall performance score 87;
- Pingdom: Perf. Grade 87/100 (Tested from New York City, New York, USA; Requests: 68, Load time: 1.59; Page Size: 1.0 Mb);
- WebPagetest.org:
до
после
Немного чисел для сравнения
Вес страницы (МБ): | Количество запросов: | Полная загрузка* (сек): | Начало отрисовки* (сек): | Google Page Speed: | Yahoo! Perf. Grade: | |
до | 1.984 | 225 | 12.11 | 2.32 | 62% | F |
после | 1.168 | 92 | 7.54 | 0.82 | 93% | B |
* значения являются приблизительными и варьируются, в зависимости от многих факторов.
Практическая скорость загрузки сайта составляет: 1.5 — 4.6 (2.9 — 5.4) сек.
Ссылки
- http://www.wp-info.ru/razgonyaem-wordpress-do-skorosti-sveta/
- http://highload.com.ua/index.php/2009/06/07/%d0%be%d0%bf%d1%82%d0%b8%d0%bc%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d0%ba%d0%bb%d0%b8%d0%b5%d0%bd%d1%82%d1%81%d0%ba%d0%be%d0%b9-%d1%87%d0%b0%d1%81%d1%82%d0%b8/
- http://developer.yahoo.com/performance/rules.html
- http://aciddrop.com/php-speedy/
- http://www.askapache.com/htaccess/speed-up-sites-with-htaccess-caching.html
- http://www.samaxes.com/2008/04/htaccess-gzip-and-cache-your-site-for-faster-loading-and-bandwidth-saving/
- http://big.eddiss.com/klientskaya-optimizatsiya/klientskaya-optimizatsiya/
- http://webo.in/articles/habrahabr/56-non-blocking-javascript/
Оптимизация картинок и графики (дополнение)
В статье был не полностью раскрыт момент, касающийся возможности оптимизации самих файлов изображений, поэтому, я попробую вкратце компенсировать это упущение.
Важным фактором клиентской оптимизации является оптимизация графики, благодаря которой можно сократить размер изображений на сайте до 30%, а в отдельных случаях, и до 90% (например, при использовании правильной оптимизации PNG). Оптимизированные изображения не теряют изначального качества. Для оптимизации всех картинок можно использовать онлайн-сервис от Yahoo — Smush.it. Для оптимизации PNG изображений без потери качества лучше всего использовать PNGOUT (Windows / Linux).
Также всем изображениям, которые выводятся в HTML при помощи тега <img> необходимо прописывать атрибуты width и height. Это действие избавит движок браузера от определения размеров изображения, тем самым мы ускорим скорость их прорисовки.
В некоторых случаях возможно поступиться некой степенью качества изображений в пользу скорости и уменьшения веса. Здесь неплохо проиллюстрирована зависимость размера изображения от качества JPEG.
Для различных изображений необходимо использовать различные форматы при сохранении:
- GIF — идеально подходит для однотонных иконок или изображений, которые используют цветовую палитру до 256 цветов. Также GIF изображения поддерживают прозрачный фон. Благодаря палитре в 256 цветов, изображения в GIF весят гораздо меньше, чем изображения в других форматах.
- JPG — самый распространенный формат изображений, который используется как в контенте, так и в служебных изображениях на сайте. JPG изображения поддерживают всю цветовую палитру, но не могут содержать прозрачный фон. Сохранять JPG изображения необходимо с качеством ~80%. Вес JPG изображений может сильно варьироваться в зависимости от качества изображения.
- PNG — используем для служебных изображений на сайте. PNG изображения поддерживают прозрачный фон и могут использовать всю цветовую палитру. Вес PNG изображений зависит от прозрачности и цветовой палитры изображения, обычно PNG изображения весят больше, чем в GIF или JPG.
Полезная статья о нюансах работы с PNG форматом опубликована на сайте студии Лебедева.
Для самых маленьких изображений, например однопиксельный background у фона сайта, рекомендуется использовать base64. Изображения в base64 уменьшают количество запросов к серверу, поскольку рисует изображение сам браузер. Закодировать изображение в base64 можно при помощи онлайн-сервисов, например: webcodertools.com. Использовать изображения более чем 1-2 px не рекомендуется, поскольку размер base64-представления будет превышать общий размер изображения и выгода в сокращении количества запросов будет нивелироваться.Пример вывода однопиксельного background используя base64:
body {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjBCNkM3QjAzMjk3ODExRTJCN0M0ODVDOUY0MzE0MjQyIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjBCNkM3QjA0Mjk3ODExRTJCN0M0ODVDOUY0MzE0MjQyIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MEI2QzdCMDEyOTc4MTFFMkI3QzQ4NUM5RjQzMTQyNDIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MEI2QzdCMDIyOTc4MTFFMkI3QzQ4NUM5RjQzMTQyNDIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4K1TALAAAADklEQVR42mL6/4cBIMAABQEB/u4q/vYAAAAASUVORK5CYII=) repeat;}
hugyugyug