Optimizing WordPress Websites

Website Speed

Website Speed

Recently a web client asked me if I could figure out why their page was loading so slowly. Simple enough question on the surface. Like any sensible web engineer I immediately opened Firefox enabled the Firebug plug-in and went to Net Panel. It was clearly evident after poking around for a few minutes that the WordPress site in question, which I built but didn’t do the design and image work for, was sized at just over a megabyte of which ~50% was images. In the scramble to get the site up and running I just took the images the designer handed me and plugged them in without any further thought then “Hey, those do look very good!” I informed the client that the images were hogging up a good bit of bandwidth and they should have a graphics expert put the  images on a diet via PhotoShop.  However, that other 50% of overall slowness that was not related to the images nagged at me.

Within the hour I had mentally resolved to figure out why the rest of the site was slow and apply anything learned to improving current and future site builds. My basic game plan after googling for a few hours and discovering YSlow was as follows:

  1. Serve the HTML gzip’ed and cached
  2. Serve the CSS/JS gzip’ed and cached
  3. Reduce the number of overall requests by combining CSS/JS files where possible
  4. Add Expires Headers
  5. Move as many images as possible externally

I know YSlow has some other recommendations, but the above are the really low fruit. With WordPress SuperCache enabled the first one is a no brainer.

The second one also seems like a no brainer – just enable apache’s mod_deflate and be done with it.  Ah, but wait a minute.  What if your host doesn’t have mod_deflate enabled?  Even if they do have mod_deflate enabled you could just be pushing your servers CPU and memory to the limit by gziping everything on every request.  Some argue to use a PHP script in conjunction with .htaccess to gzip on the fly.  Again, your just straining the server needlessly all the time. The solution I settled on is to minify and gzip the CSS/JS files on the webserver into psuedo .gz extensions (e.g., *.css = *.css.cgz and *.js = *.js.jgz) with the following script:

#!/bin/sh

# minify and gzip css and js files, Apache .htaccess
# will deliver them to the client encoded

# WP core css files are not minified. All WP core css files and theme files
# are minified and then gziped.  WP core js files are all already minified.  Some of
# the theme files are also minified, but a few are not.  Experiments show that
# minifying theme files caused rendering problems and gave very little
# optimization, so we don't bother to minify them.

yuicomp='yuicompressor-2.4.2'

# gzip all css files
for i in `find . -type f -name "*.css"`; do
echo "minifying and gziping $i"
java -jar $HOME/java/${yuicomp}/build/${yuicomp}.jar --nomunge $i > ${i%.*}.min.css
gzip -c ${i%.*}.min.css > ${i}.cgz
rm -f ${i%.*}.min.css
done

# gzip all js files
for i in `find . -type f -name "*.js"`; do
echo "gziping $i"
gzip -c $i > ${i}.jgz
done

Note, WordPress core JS files are already minified so you only need to gzip.  Further, be careful minifying JS files as there are sometimes unintended consequences.  Given the performance and headache trade-off I only gzip JS and don’t bother to minify.

Then add the following to .htaccess file:

RewriteCond %{HTTP:Accept-Encoding} gzip

# serve gzipped css
RewriteCond %{REQUEST_FILENAME}.cgz -f
RewriteRule (.*)\.css$ $1\.css.cgz [L]
AddType "text/css" .css.cgz
AddEncoding gzip .cgz

# serve gzipped js
RewriteCond %{REQUEST_FILENAME}.jgz -f
RewriteRule (.*)\.js$ $1\.js.jgz [L]
AddType "text/javascript" .js.jgz
AddEncoding gzip .jgz

Third item turns out to be a real hassle in WordPress.  WordPress is a great CMS that offers a great environment for themes and a diverse selection of plugins. But the price is an architecture where components are spread about a large file tree in a fashion that makes it nearly impossible to combine CSS/JS files without threatening to break when WordPress core, plugin, and theme upgrades roll in which is frequently. I didn’t bother as it just seemed too dangerous to even think about touching with the proverbial ten foot pole.

Number four is another apache related issue.  Either you have, or can have via your host, mod_expire enabled or you don’t.  If you do then it’s just as easy as the following .htaccess line to get the ball rolling:

ExpiresActive On
ExpiresDefault "access plus 1 week"

Remember, though, this assumes your server controls the request.  If you have a large image file on your site that loads frequently and you moved it to Amazon S3 to reduce you load time and bandwidth (IMHO – probably a good move most of time) chances are the external host will not expire the image at all.

Lastly, try to move your big images to an external host like PhotoBucket. Let PhotoBucket deal with the overhead and if you need to pay them for a Pro account. It’s worth a mislay $20/year so that your loyal online readers don’t have to suffer through frequent slow page loads.

Speaking of loyal readers I have applied the lessons from this post to the site and it’s definitively faster!

Categorized: Tech

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>