Optimizing ExpressionEngine Sites for Minimum Load Times [Part 1]

Posted on 04. May, 2009 by Jack in Development, ExpressionEngine

Optimizing ExpressionEngine Sites for Minimum Load Times [Part 1]

I’m going to focus on ExpressionEngine sites here, but most of these techniques can really be applied to nearly any website. While writing this i realized i should really break it into two parts. This first part will be most of the low-hanging fruit on into some mid-range optimization, while in part two i’ll get into more complex query caching, expires headings, content delivery networks, and Entity Tags (Etags).

Load Optimization is a lot of little things added together for the greater good. When combined, page weight can be cut in half, or even more, with no change in functionality. Start with the lowest hanging fruit and move up to the more complex and more gritty as needed. I’ve found that 2 or 3 “out-of-the-norm” techniques will get you 80% of the way to a superfast loading site. Standard 80/20 rule.

I’ll break the modifications down into 3 categories:

  1. Requests
  2. Sizes
  3. Queries

Before I get into the gritty details, I’d first recommend a tool to benchmark and compare performance as you work through these tips. My favorite tool is YSlow, a Firebug Addon for Firefox. It breaks your site down into a number of elements and grades you on a set of (mildly) arbitrary benchmarks. Great place to start. Compare your progress as you move forward. Find what gives you the best boost and try to replicate those changes on every site.

1. Requests

The more files you request (HTTP Requests), the slower your site load. In addition, the ORDER in which you request them and WHEN you request them can play a factor as well

  • Combine as many javascript functions/libraries/plugins as you can in a single include. I’m a huge offender in this category, sometimes with 8 to 15 javascript includes. Sites have to load these 1 at a time, in sequence. Try and keep it to 5 or 6 at max. Less is more.
  • If you can’t combine javascript, try loading them right before your closing </body> tag. If they’re not needed for onLoad effects, at least your visitors won’t have to wait for the visuals
  • CSS Sprites. Background images are a load-speed culprit . If possible, sprite (a technique where you combine a number of elements into one image and position them as needed) as many elements as you can. It takes a little while but it’s worth it. Check out YouTube’s master sprite. THAT’S optmization. There are many tutorials online for this technique, just Google “CSS Sprite” or “How to CSS Sprite.” You’ll survive.
  • I know a lot of people like to separate their CSS (style.css, layout.css, text.css, reset.css, ie6.css, ie7.css, etc….) for organization’s purpose, but every request adds just a little bit to your load time. It’s best to simply roll it into 1 to 2 main files (i like keeping a reset.css and 960.css combined for those applicable when using the grid, plus my main css sheet).
  • Try using Google hosted jQuery/MooTools/Prototype includes. Chances are people will have these cached from visiting another site and will save a request. At least it will save you bandwidth
  • Caching. There are a number of different levels you can approach here. First and most straightforward is ExpressionEngine template caching. Once your site is out of development, turn caching on for all major templates that don’t change at a moment’s notice. My general rule of thumb is 5 minutes for major templates (home page, first level landing pages, nav includes, etc) and 60 minutes for less used templates (contact form, sitemap, etc). Secondly, if you have templates that just change too often, maybe you have {exp:weblog:entries} tags that don’t change often, such as an intro paragraph to a news section or something similar. You can actually cache your tags. Example:
    cache="yes" refresh="30"

2. Sizes

I’m going to assume you’ve already optimized all your images. You wouldn’t be here if you were looking for that tip. (Save-for-web @ 100% ;)

  • Minimify your javascript. This gets rid of any extra markup, whitespace, etc… to save precious kb. Check out the YUI Compressor (http://developer.yahoo.com/yui/compressor/) to get those bad boys down in size.
  • Gzip your javascript files. This gives me awesome results everytime. Once i tried this i never went back. It can change depending on your server, but as long as you’re on a LAMP stack, this should get you close. You’ll need to have mod_deflate loaded in PHP for starters. Behond that, it’s really a simple .htaccess update. I prefer to set it up to gzip everything and exclude the files i don’t want compressed (images, zip and rar files, gz, etc…). This usually cuts my js file sizes in HALF. The following .htaccess info should be able to be dropped right in your site.
# Gzip Our Scripts
######################################################
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ \
no-gzip dont-vary
SetEnvIfNoCase Request_URI \
\.(?:exe|t?gz|zip|bz2|sit|rar)$ \
no-gzip dont-vary
SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary
# Just in case some noob is using an old browser...
######################################################
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

3. Queries

Hopefully you’re doing this already, but disabling any parameter you don’t need in a {exp:weblog:entries} tag will help to speed up the query process and thus your site.

  • My standard disable string is disable=”member_data|categories|trackbacks|pagination”.
    I usually leave category_fields and (of course) custom_fields out of there.

I try to do all these tweaks on all my sites. So far, i’ve cut average load times from 4 seconds to under 1.3 seconds across the board. Simply by using these techniques. Give it a shot.

That’s it for part one! If anyting doesn’t work or you’d like to add your tips, feel free to comment and i’ll add your tips in (and give you credit of course). I hope it helps you.

Tags: , , , , ,

8 Comments

Martin Luff

05. May, 2009

Hi Jack

Great roundup there of the basics – thanks for that. Can’t wait for the follow-up ;-) For the CSS sprites there are some usful resources like http://spritegen.website-performance.org/ – generates the sprite and the CSS once you have the individual images all done and dusted…

Would be great to see something on performace impact of single templates with many embeds versus more templates few embeds, or more templates versus lots of {if:esleif } arguments…

Thanks again.

Doug Avery

19. May, 2009

Awesome overview, thanks!

We’ve also found that reducing the number of weblog tags on a page, even if they’re hidden behind a “if” statement, is key. These tags seem to request and render before the if statements process, meaning they can be a huge issue if you’re not paying attention.

Jack McDade

26. May, 2009

@Doug Interesting. I haven’t noticed the {if} statement being a big factor. I’ll have to run some benchmarks and see what level of increase you can get from cleaning them up.

Gareth du Plooy

27. Jul, 2009

This is very very helpful. I noticed with official EE documentation, they say for template caching that : “We call it Dynamic Page Caching because the system will clear itself automatically when certain events happen. For example, if you cache your comments page, when someone submits a comment, the cache will be cleared, momentarily overriding the normal caching preferences.”

If I have a EE template page that my client’s iPhone app hits with just the weblog results (no other html is returned), and I have the template cache set at say 1 minute, would posting a new article automatically refresh this template? I can’t seem to find answers to this anywhere!

THanks!

Jack McDade

27. Jul, 2009

@Gareth If you’re talking about live, on the fly refreshing, no — it wouldn’t do that. But it’ll remove the cache so next time they view it, they’ll re-download the whole page rather than pull up the cache. Make sense?

Brian Klepper

29. Jul, 2009

Thanks for the info. I think I should double check my queries!

Tom Davies

13. Aug, 2009

Hey Jack,

Great article – I use minify (http://code.google.com/p/minify/) to automate combining and compressing CSS + Javascript while keeping the organisational advantages of separate files for development and maintenance. It’s a dead easy install and automatically refreshes its caches when you edit a file – check it out.

keep up the good work!

Jérôme Coupé

14. Aug, 2009

Thanks for the tips.

Episode 11 of Ryan Ierland’s excellent screencasts goes in depth about available caching options in ExpressionEngine.

http://www.pragprog.com/screencasts/v-riexp/building-a-dynamic-website-with-expressionengine

Leave a reply