Recently I was asked about some of the techniques I use to optimize the speed of WordPress outside the normal advice of reducing header request, CDN, minify stuff, etc. These steps help me implement changes for a basic Apache setup very quickly with minimal configuration and problem solving.
This post is also titled “why shared hosting is a bummer” because my main recommendation of installing bytecode optimization like APC ( see below) is not available on 99% of shared hosts. Why?
- They don’t like you eating up all the rams when they need it for the other 5k people on your server
- It’s finicky to configure
- It would start a fire and all the admins would quit
Why do you want bytecode optimization to begin with when you have plugins that do static file caching you say? Well static caching is great, really, but if your site is running lots of code on each request, doing dynamic things, and using the CPU, then your going to want to optimize processing as well.
So ya, shared server not so hot.
This post is about what you can do quickly without using plugins, but generally speaking you should be using a plugin that caches static files and takes advantage of APC and/or Memcache. For more advanced needs consider a proxy cache like squid or varnish. I wrote a post which has some benchmark data comparing W3 Total Cache, Super Cache, Batcache vs a default install, it’s a pretty crummy test but interesting.
Four things I will cover:
- Opcode caching (server-side)
- Browser caching and compression
- Image optimising
- JS tips
Total files added to WordPress = 1 .. (2 combined with batcache)
Time investment: > 5min + a few more afk
So lets start with something that is really easy to implement and highly effective.
APC is a “PHP bytecode compiler that stores the final, compiled result in shared memory.” In layman’s terms, a lot of the processing that WordPress is doing can be stored in memory instead of run on each request. Read more about how APC works, or don’t it’s pretty boring.
To really take advantage of APC install the following:
Since this is a drop-in, it is not installed like a regular WordPress plugin, instead you just drop it in your
/wp-content folder. You should then see it in your Admin under Plugins–>Drop-ins.
Twenty Twelve theme with the official imported sample data – home page without APC.
Same exact page refreshed with APC.
Pretty significant wouldn’t you say?
Installing APC is really straightforward, you can check if you have it installed by creating a PHP info file, http://php.net/manual/en/function.phpinfo.php, if you have APC installed you should see:
or you can run the following at the command line to check for APC:
php -r "phpinfo();" | grep apc
If you need to install APC , Google the process because it depends on your OS or ask your host, it basically consists of 3 easy steps (on linux it takes about 1 minute):
- Download from PECL, or use the PEAR installer: http://pecl.php.net/package/APC
- Edit your php.ini or config file to include APC
- Restart Apache
Note: ZendOptimizerPlus was just open sourced while I was writing this, it will most likely replace APC and eventually be bundled with PHP.
Browser cache and compression
You can quickly leverage the power of apache’s .htaccess file to perform two tasks that increase performance, setting the browser cache for assets and enabling compression.
I use the HTML5-boilerplate .htaccess file which was originally developed by Paul Irish and now has hundred of contributors. It’s part of a much larger framework so it’s worth looking at the whole thing, but you can just grab the .htaccess file. If you already have a WordPress created .htaccess file (if you changed the default permalinks) then just copy/paste the whole boilerplate below it.
You will need to comment out the default # Option 1 rewrites (line 365- 369), since we want WordPress to handle this. Also read the inline comments for further options.
To test out if your site’s assets are cached open up Chrome developer tools network tab( or Firebug) and check the headers for all the files , you should see stuff like this:
This file will also enable GZIP compression and some other neat options.
Looking for something more advanced , check out mod_pagespeed from Google: https://developers.google.com/speed/pagespeed/mod
Images are almost always the primary source of slow loading websites, there is no all in one solution, I take several steps to insure that optimal images are loaded throughout the lifespan of a site.
Tips for creators
- When possible always use PNG-8.
- Avoid using CSS/HTML to re-size images
add_image_sizeto add additional sizes for your site. Optimization > Storage (storage is cheap).
- Use command line tools to compress and optimize images without any quality loss. I typically see a reduction between 5-10% on images that have already been through Photoshop..
I prefer a command line tool because smushing images takes considerable CPU, and you can go AFK without anything blowing up.
5. Stop using shitthumb.php , aka timthumb.
6. Avoid using the
$content_width WordPress Global. This feature is used in the default WordPress themes (and others), it will re-size images using HTML yet load the original, meaning in many cases you end up loading 2x or more data, I wrote more about it here https://wycks.wordpress.com/2013/02/14/why-the-content_width-wordpress-global-kinda-sucks/ .
I’m sure everyone has had a client or friend upload 5MB photos images directly from a camera, when I first started using WordPress I worked on a site that was almost 100MB per page load because of this. There are some plugins on wordpress.org that attempt to solve the problem but I have yet to try them out, maybe someone can recommend one? One option is to just block the upload limit using php.ini, another is to try this function found here http://wordpress.stackexchange.com/questions/76602/how-can-you-set-maximum-width-for-original-images but I could not wrangle it to work very well.
Recently I’ve been trying a technique to control what the user can do by creating a “max-size” for images inserted into a post and removing the ability for them to insert full size ones. It’s a decent solution which also handles the
$content_width Global issue mentioned above, but does require customization for each site and has some major drawbacks (changing themes). I created a filter on Gist to do this.
Of course if you want a more advanced tool, Chrome Developers’ timeline feature provides it, but Speed Tracer is also useful, check out a quick video overview on YouTube.
Also don’t forget to utilize the DOMContentLoaded event in Google Dev tools in the bottom bar of the Network tab, it’s super useful to compare it to the “onload” time.
The DOMContentLoaded is fired when the document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading (the load event can be used to detect a fully-loaded page). (https://developer.mozilla.org/en-US/docs/Mozilla_event_reference/DOMContentLoaded_(event))
The last tip,
When in doubt throw more ram at it, it being the server.