Ускоряем wordpress

Привет.
Думаю, среди читателей моего блога немало тех, кто имеет stand-alone blog на движке wordpress.

Так вот, для вас, дорогие мои, у меня есть две новости, как водится, плохая и хорошая.
Плохая состоит в том, что wordpress - довольно-таки тормознутая штука.
Виноваты в этом в основном криворукие производители тем и, особенно, криворукие производители плагинов.

особенно кривой плагин, на мой вкус, wp-ajax-edit-comments, который является образцом быдлокодинга

Хорошая - в том, что это можно поправить. Сейчас дядя Саша научит вас, как.

## Теория ##

Сначала немного теории. Уже довольно давно умные люди из компании Yahoo провели исследования на тему “как же нам ускорить наши сайты”. И выяснили, что на скорость сайта _с точки зрения пользователя_ в основном влияет оптимизация front-end’a, а не server-side. Подробнее об этом можно почитать на сайте webo.in (кстати, отличный ресурс, посвященный оптимизации времени загрузки веб-сайтов) на русском и на сайте yahoo на английском, я же просто опишу несколько простых шагов, которые позволят существенно ускорить скорость работы своего блога.

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

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

## Практика ##

#### Оптимизируем тему ####

Да, открытость платформы Wordpress - это очевидное благо. Я серьезно.
Множество прекрасных дизайнеров, верстальщиков, программистов с горящими от энтузиазма глазами вдохновенно, вдумчиво создают темы и плагины для всех, для всего человечества, не требуя ничего взамен. Это действительно прекрасно.

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

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

Таким образом, нам надо исправить недостатки, которые (возможно) присущи вашей любимой теме от рождения и поправить ее код.

Итак, для того, чтобы тема стала работать быстрее, надо сделать следующее:

1. Если тема сверстана на таблицах, переверстать ее на дивы. Я не буду касаться давнего спора “как вестать - дивами и таблицами”, замечу только, что точки зрения поставленной перед нами цели (быстро работающий с точки зрения пользователя блог) таблицы проигрывают дивам - потому что таблица отрисовывается браузером только после того, как будет полностью загружена, тогда как дивы отрисовываются сразу, как только браузер получит их с сервера. А значит, если страница сверстана в дивах, пользователь быстрее увидит контент сайта, что нам и нужно, не так ли?
2. Вы будет смеяться, но нужно убрать все стилевые правила во внешние файлы. И JavaScript - тоже. Это настолько очевидно, что я даже не буду пояснять, зачем это нужно.
3. Внешний стилевой файл прописываем в блоке head, а JavaScript файл подключаем как можно ближе к закрывающему тэгу “body”. И все скрипты аналитиков тоже располагаем пониже.
4. Сжимаем js и css. Для этого мы будем использовать yui-comressor. Делается это примерно так: качаем последний стабильный релиз YUICompressor’a с официального сайта, устанавливаем, если еще не установлено JRE и выполняем на css/js файл команду следующего вида:

java -jar /path/to/yuicompressor-*.*.*.jar -o "output_filename" $file

можно использовать флаг -type, который указывает, какой тип файла. Если флаг не указан, то тип файла определяется по расширению.

Можете использовать тему моего блога как пример.

#### Уменьшаем количество файлов ####

Так как мы можем серьезно ускорить скорость загрузки файлов, уменьшив число этих файлов (удивительно, правда? :), то разумнее всего будет слить все css-файлы и js-файлы в один. Если эти файлы размером больше ~70 килобайт, то лучше разбить их на два куска.

Если нужно уменьшить количество картинок, используя технику css спрайтов и технику image map.

Тут надо отдельно заметить, что у многих (практически у всех) плагинов есть совершенно идиотская особенность - прописывать свои js и css файлы. Идиотизм заключается в том, что очень часто разные плагины используют одну и ту же, скажем библиотеку, и подключают ее по нескольку раз. И пользователь, просматривающий ваш блог, вынужден по два-три раза грузить, к примеру, prototype или jquery. Лишние ~30-160 KB. Неслабо, прадва?

Тех. заметка: при этом совершенно непонятно, что мешало создателям wordpress сделать контроль надо всеми ресурсами, что прописывают плагины. К примеру, если один плагин, которому нужен jQuery, прописывает тэг script с jQuery и рапортует - “Вот мол, подгрузил, все, кому надо, могут использовать”, а другой, которому тоже нужен jQuery уже знает об этом и не подгружает свой вариант

Лечится это так - все скрипты, что подгружают плагины слейте с теми, что написали сами и воткните в футер, а плагинам запретите их подгружать. Тоже самое сделайте с css, только воткните в header.

#### Оптимизируем графику ####

Картинки в png и jpg форматах довольно часто неоптимизированы и хранят много лишней информации. Было бы неплохо избавиться от этой лишней информации и таким образом сжать файлы. Делается это с помощью специальных утилит. Это позволит нам уменьшить их размер в отдельных случаях на 50 процентов. Неслабо, правда?

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

Информацию об этих утилитах и команду я позаимствовал у Дмитрия Ищенко. Надеюсь, он не в обиде :)

Итак, для оптимизации всего png картинок мы будем использовать pngcrush. Я затрудняюсь ответить, как ее инсталлировать на windows или linux, но я на своем mac’e без проблем установил эту утилиту из портов.

Чтобы сжать png-файлы без потери качества, используйте следующую команду:

pngcrush -rem alla -reduce -brute image.png result.png

Для сжатия jp(e)g-файлов используйте jpegtran, которая входит в пакет libjpg, который я также установил из портов. Команда для сжатия jp(e)g-файлов без потери качества:

jpegtran -copy none -optimize -perfect src.jpg dest.jpg

Я тут набросал shell-скрипт, который рекурсивно пройдет по директории и оптимизирует все png/jp(e)g картинки в ней:

for file in `find . -iname "*.jpg" -or -iname "*.png" -or -iname "*.jpeg"`;do
    ext=${file##*.}
	if [ -n "$ext" ]; then
		if [ "$ext" = "jpg" ]; then
            echo "optimizing ${file} as jpeg file with jpegtran"
            jpegtran -copy none -optimize -perfect -outfile temp_abracadabra_filename.jpg $file 
            mv -f temp_abracadabra_filename.jpg $file;
        fi
        if [ "$ext" = "jpeg" ]; then
            echo "optimizing ${file} as jpeg file with jpegtran"
            jpegtran -copy none -optimize -perfect -outfile temp_abracadabra_filename.jpeg $file
            mv -f temp_abracadabra_filename.jpeg $file;
        fi
        if [ "$ext" = "png" ]; then
            echo "optimizing ${file} as png file with pngcrush"
            pngcrush -rem alla -reduce -brute "$file" temp_abracadabra_filename.png;
            mv -f temp_abracadabra_filename.png $file;
        fi
	fi
done;

Просто выполните его в директории uploads что в папке wp-content и все будет хорошо. Можно даже повесить его на cron-job и больше не париться на этот счет - все вновь прибывшие файлы будут оптимизироваться.

Разумеется, надо оптимизировать графику, используемую в теме, так что вот еще один shell-скрипт, который рекурсивно пройдет по директории, сожмет css, js файлы и оптимизирует jp(e)g/png файлы. На всякий случай перед его использованием не забудьте забэкапиться:

for file in `find . -iname "*.jpg" -or -iname "*.jpeg" -or -iname "*.png" -or -iname "*.js" -or -iname "*.css" `;do
    ext=${file##*.}
    if [ -n "$ext" ]; then
        if [ "$ext" = "css" ]; then
            echo "compressing ${file} as css file with yui compressor"
            java -jar /opt/yuicompressor/yuicompressor-2.3.5.jar --type css -o "temp_abracadabra_filename.css" $file 
            mv -f temp_abracadabra_filename.css $file;
        fi
        if [ "$ext" = "js" ]; then
            echo "compressing ${file} as js file with yui compressor"
            java -jar /opt/yuicompressor/yuicompressor-2.3.5.jar --type js -o "temp_abracadabra_filename.js" $file 
            mv -f temp_abracadabra_filename.js $file;
        fi
        if [ "$ext" = "jpg" ]; then
            echo "optimizing ${file} as jpeg file with jpegtran"
            jpegtran -copy none -optimize -perfect -outfile temp_abracadabra_filename.jpg $file 
            mv -f temp_abracadabra_filename.jpg $file;
        fi
        if [ "$ext" = "jpeg" ]; then
            echo "optimizing ${file} as jpeg file with jpegtran"
            jpegtran -copy none -optimize -perfect -outfile temp_abracadabra_filename.jpeg $file
            mv -f temp_abracadabra_filename.jpeg $file;
        fi
        if [ "$ext" = "png" ]; then
            echo "optimizing ${file} as png file with pngcrush"
            pngcrush -rem alla -reduce -brute "$file" temp_abracadabra_filename.png;
            mv -f temp_abracadabra_filename.png $file;
        fi
    fi
done;

Используйте меньше dns-lookups. Не выкладывайте картинки, src которых указывает на другой ресурс, лучше загрузите их к себе и пропишите ссылку на автора. Работать будет быстрее.

#### Сжатие ####

Все современные браузеры поддерживают сжатие, так что можно существенно уменьшить размер отдаваемых файлов (а значит, и время их загрузки) при помощи mod_deflate (для Apache 2.2 для Apache 1.3 надо использовать mod_gzip). Так что включите mod_deflate. Если же вы используете Apache 1.3, ниже приведенный код вам не не нужен, вам поможет статья “mod_gzip — сжатие html страниц ‘на лету’” на сайте webo.in.

Найдите файл .htaccess в корневой директории установки wordpress и добавьте в конец следующее:

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/xml
    SetOutputFilter DEFLATE
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
    SetEnvIfNoCase Request_URI \.(?:gif|png)$ no-gzip dont-vary
    Header append Vary User-Agent env=!dont-vary
</IfModule>

Таким способом можно добиться уменьшения js/css/html файлов на 70-80%, и примерно 10% уменьшения jpeg-файлов, что значительно ускоряет загрузку сайта. Следует, правда, помнить, что использования mod_deflate увеличивает нагрузку на сервер, так как ему нужно сжать файлы перед тем, как отдать их, так что стоит проконтролировать, что использование mod_deflate не создает чрезмерной нагрузки на сервер.

#### Кеширование ####

Ну и последнее - для того, чтобы ускорить серфинг по вашему сайта нужно врубить кеширование. Это не ускорит загрузку сайта у пользователя, который первый раз пришел на ваш сайт, но положит все внешние js, css файлы, картинки к нему в кеш, и в следующий раз, когда он будет бродить по вашему сайту, ресурсы будут грузиться не с сервера, а из кеша, что значительно ускорит скорость работы вашего сайта с _точки зрения пользователя_, а также значительно снизит нагрузку на ваш сервер. Помните, что закешированные у пользователя файлы берутся из кеша браузера, поэтому, если вы внесете изменения в файл, скажем, стилей, пользователь, закешировавший style.css, не увидит их. Так что лучше включать кеширование после того, как вы доработали тему.

Опять же, добавьте следующие строчки в конец файла .htaccess и не забудьте включить mod_headers и mod_expires (или хотя бы один из них):

# используем mod_expires
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault A86400        
    ExpiresByType image/x-icon A2592000
    ExpiresByType application/x-javascript A2592000
    ExpiresByType text/css A2592000
    ExpiresByType image/gif A604800
    ExpiresByType image/png A604800
    ExpiresByType image/jpeg A604800
    ExpiresByType text/plain A604800
    ExpiresByType application/x-shockwave-flash A604800
    ExpiresByType video/x-flv A604800
    ExpiresByType application/pdf A604800
    ExpiresByType text/html A900
</IfModule>
# используем mod_header
<IfModule mod_header.c>
    # 3 Month
    <FilesMatch "\.(flv|gif|jpg|jpeg|png|ico|swf)$">
        Header set Cache-Control "max-age=7257600"
    </FilesMatch>
    # 1 Week
    <FilesMatch "\.(js|css|pdf|txt)$">
        Header set Cache-Control "max-age=604800"
    </FilesMatch>
    # 10 Minutes
    <FilesMatch "\.(html|htm)$">
        Header set Cache-Control "max-age=600"
    </FilesMatch>
    # NONE
    <FilesMatch "\.(pl|php|cgi|spl)$">
        Header unset Cache-Control
        Header unset Expires
        Header unset Last-Modified
        FileETag None
        Header unset Pragma
    </FilesMatch>
</IfModule>

#### Кеширование на стороне сервера ####

Есть несколько плагинов к wordpress’у, которые позволяют кешировать файлы на стороне сервера. Работают они по такому принципу: как только какая-то из ваших страниц запрашвается на сервере, она динамически строится и создается html-файл со всеми данными, который ложится в кеш. Как только приходит запрос на эту страницы, пользователю отдается html файл вместо того, чтобы динамически строить страничку, что значительно снижает нагрузку на сервер (теперь ведь не прогоняются php-скрипты и не нагружается база данных).
К сожалению, все эти плагины работают как-то очень странно, во всяком случае, у меня не работали должным образом ни wp-cache, ни работающий на его основе wp-super-cache.
Зато работает 1 Blog Cacher, правда, у него достаточно сложная настройка. Надеюсь, вы разберетесь. Я использую его.

#### Итого ####

После того, как я провел над своим блогом ряд этих нехитрых действий, блог стал загружаться на 80% быстрее.
Теперь perfomance meter моего сайта с точки зрения плагина к firebug’у YSlow равен B(85), был F(33). Думаю, неплохой результат.

Viewing 10 Comments

 
close Reblog this comment
blog comments powered by Disqus