A few months ago while debugging a Wordpress site and outputting queries into a log, I noticed that queries were getting fired for pages that I wasn’t even looking at. After a baffling search, I found out that Firefox was prefetching the next post based on the rel=”next” meta tag.
For example, on my Fish Taco Blog site, this is an example rel=”next” meta tag that Wordpress automatically generates:
<link rel='next' title='Chat Chew' href='http://www.fishtacoblog.com/new-york/chat-n-chew/' />
When viewing a post in the single.php template, Wordpress will output rel “next” and “prev” tags by default. Firefox then consumes this information and makes the decision to load the next page before you browse to it. The idea is that once you are browsing posts, you may be more likely to visit the next post in the sequence, possibly via the next post link that is present in many Wordpress themes, and it will now be locally cached by Firefox, speeding up page load time for when you actually do click on it.
Sure, this wouldn’t hurt most blogs – it’s a feature that enhances the user experience. However for high traffic blogs, and Wordpress sites that aren’t built on the traditional post concept, this feature is unnecessarily and possible harmful to performance.
To remove these tags from Wordpress site, add the following to your theme’s functions.php file:
//remove auto loading rel=next post link in header
remove_action('wp_head', 'adjacent_posts_rel_link');
Here’s Mozilla’s background information on prefetching, and it should be noted that this currently only happens in Firefox, not Internet Explorer.
Often as a site grows, its performance degrades sharply. This can happen for many reasons, and is typical for a site that continually undergoes maintenance. As a project ages, the content often grows as well. More data, more code revisions, more ideas to turn into code for the site, etc.
I’m exploring this subject because a site of mine is in need of a performance boost. It was a snappy little site when I first launched it, but I’ve had many more ideas since then, and I’ve implemented almost all of them. Now regular browsing through the site is noticeable slower.
I’ve got a short list of performance enhancing ideas that I’m going to explore below.
Separating CSS and JS Files
For starters, if you have inline CSS or JS, you should separate these into separate files. This is a huge performance win, because a browser can cache mystyles.css or javastuff.js, but can’t cache it if it’s included inline in your page source code. Most performance wins happen client side – taking advantage of caching is often more efficient than making slight changes to server side code, though this isn’t a rule that’s set in stone; You could have terrible server side code that slows down the site too. My site in question already has the CSS and JS files separated, but it’s worth mentioning in case you haven’t done this.
Minifying CSS and JS Files
This is something that enterprise many sites do, so I thought I would go ahead and do this. Basically, it means removing spaces,tabs, and line returns wherever possible so that the file size is smaller, but the code executes as normal. When minifying a CSS file, I prefer to leave one CSS selector per line, and then listing each CSS property after it. This reduces file size, but makes the file still human readable/editable.
Here is an example of a fully minified CSS file from MSN – http://tk2.stc.s-msn.com/br/hp/11/en-us/css/hp_1.css – I think this is overdoing it, and doing it this way is probably done through an automated script, as this would be next to impossible for a developer to edit in a development environment.
For complex sites, this is going to be a better win than for simple sites. I saw about a 20% decrease in file size. For very, very simple sites (read very), using an external CSS file can slow things down because of the server disk access time of retrieving the external CSS file. The original Google page, for example, only has a few lines of CSS, and therefore uses inline CSS. For anything more complicated, include it in an external file.
Reducing Image Use
Many blogs and news oriented sites use too many images. This slows things down for first time readers, who don’t have the images cached. A good tool to examine load times of everything on your site is Firebug, a plugin for Firefox. You can get the latest version of Firebug here. The image below is a screen capture of one of the features in Firebug that lets you examine exactly how long everything took to load. If your site is nearing half a megabyte (~500kb), it’s time to put less on your pages, or use smaller images.

Using Less Database Queries
This is very important on some sites, and irrelevant on others. If you are using a basic installation of Wordpress, for example, there really aren’t too many ways for an average person to speed it up, without writing the developers and telling them to use less queries next release. For heavily customized sites based on existing platforms and fully custom database driven sites, database queries can be the make or break of your site performance. Basic rule: if you are writing your own queries, and you don’t know how they perform, then you shouldn’t be writing your own queries. Having said that, never outright trust queries from other somewhat experienced developers. Developing for my firm, a Fortune 500 company, we have often encountered popular plugins for Wordpress or modules for Drupal that have queries in them that are written poorly. Just because another developer made it, doesn’t mean they did it right.
Another way to use less queries, is to outright display less content. This is easy to accomplish if you’re using a blog platform. If you’ve got 20 posts a page, reduce this number. The number of queries your blog site makes is directly proportional to the number of posts or entries it is trying to display.
Better Hosting Plan or Better Hardware
This isn’t an option for me, because the next level of hosting plans with GoDaddy is out of my current budget range. For others, however, it may be an option. It’s worth looking into.
Wordpress, the engine that is behind the post you are currently reading, is easy to upgrade with most hosting environments. However, upgrades can get tricky in locked-down enterprise environments.
For the most secure environment, the MYSQL database user that is used by Wordpress (hardcoded in your wp-config.php file) to retrieve and set information should not have Drop, Alter, and Create database privileges. If it did, malicious code would have an easier time disrupting the database. This is a problem because upgrading Wordpress usually involves some major additions or changes to the database structure, for which these privileges are needed.
So what is the solution? Basically it is running the upgrade as the root user. But, hardcoding root credentials in your wp-config.php file for a little bit is not good security practice, even if you change it back afterward. What you need to do is run an SQL script with all the database statements that are required for upgrade directly on the MYSQL server, or by using the MYSQL command line client.
Capturing the upgrade sequence is a little more difficult. Most enterprise installations have a development environment with looser security, possibly only accessible from inside the firewall of your organization. If your development environment is setup with a database user that does have alter, drop, and create credentials you’re in good shape.
Open up the /wp-includes/wp-db.php file and find the query() function. This is the function that Wordpress calls before each and every database call. On the first line of the function, add this line:
error_log($query);
This will output each query into your PHP error log file. Empty this file before attempting an upgrade on your development environment. Wordpress upgrades involve replacing all core files, and then logging in to the admin interface and upgrading the database by clicking a prominent upgrade button. After you have done this, the error log file will contain all the queries run by the upgrade.
There are more queries in here than are necessary to upgrade Wordpress. Delete all select queries, leaving a combination of alter, drop, create, or insert statements. Rename the error log file upgrade.sql and you’ve got the entire database upgrade in a ready to run script.
Publish the changed files up to your live environment. Your site will stay up even if a database change is required in the back end – this is a feature of Wordpress allowing for easier upgrades without site downtime. Next, run your upgrade.sql script with root privileges, or send it to your DBA team to run. You’re all upgraded, and you kept your site secure the entire time.
This same process can be used for upgrades to Wordpress Plugins, which often also require Alter, Create, and Drop statements to their tables.
Creating blog posts is extremely easy in Wordpress, but adding simple thumbnails to your posts is not. I’m not talking about adding images within the post content, but adding them to your theme so they display in a standardized way in your blog loop, and on individual post pages.
The problem is that though Wordpress allows inserting images within posts, there is no way to “attach” these images to the post, so that theme designers can pull standardized images out for display. By making a few changes to your Wordpress configuration and your theme templates, and by using the Post Thumbnails plugin that I have written, you will be able to add thumbnails to your site in an intelligent way.
Wordpress Configuration
First step is to login to your Wordpress admin dashboard and navigate to the Settings -> Miscellaneous page. Here you will need to change:
- Uncheck the “Organize my uploads into month- and year-based folders.”
- Change the Wordpress thumbnail size to your desired size. This is important! Take careful thought when making this decision – you will break old post’s thumbnails if you chose to change this value later. I recommend 50×50 pixels.
Plugin Installation
Download the Post Thumbnail plugin using this link. Unzip it and place the file within your wp-content/plugins/ directory. Navigate to the Plugins menu within the Wordpress admin dashboard and activate this plugin.
You’re going to need a default post thumbnail to be used when no image is associated with a post. Upload an image that is the same size as the thumbnail size you chose above to the wp-admin/uploads folder, or the same folder you have chosen for uploads if you’re using a custom location. On most installations that folder would be wp-content/uploads/.
After you’ve uploaded the image, paste the name into the first line of code in the plugin PHP file:
define('DEFAULT_POST_THUMBNAIL', 'default_thumbnail_file.jpg');
Change the above default_thumbnail_file.jpg to whatever your image was called.
Plugin Usage
After the plugin has been activated, you will notice a new box titled Post Thumbnail on the Wordpress Write and Edit screens. To get a thumbnail attached to your post, upload an image using Wordpress’ default image uploading mechanism, which is a button next to the Add Media label near the top of those screens. This opens up a popup window for uploading images. Upload your image, but you don’t need to insert it into the post. Instead copy the file name (ex. myimage.jpg) and then click on the X to close the window.
Next, paste the file name into the Source Image input field in the Post Thumbnail box and click save. After saving, you will notice that an image name will be displayed in the Generated Thumbnail box. This is the thumbnail version of your source image, that Wordpress resized for you when you initially uploaded the image.

Adding the Thumbnail to Your Theme
Now that thumbnails are being attached to posts, we need to modify our theme to display them. It’s up to you to decide where you want to place them, but I would recommend adding the thumbnail to your template wherever you use the Wordpress loop. Below is a code snippet that inserts a thumbnail into the Default Wordpress theme’s index.php file, so thumbnails will show up on the main page of your site. Only one new line needs to be added.
<?php while (have_posts()) : the_post(); ?>
<div class="post" id="post-<?php the_ID(); ?>">
<h2>
<!-- Begin New Code-->
<div style="float:left; margin:5px;">
<?php echo get_post_thumbnail(get_the_ID()); ?>
</div>
<!-- End New Code-->
<a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to
<?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
<small>
<?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> -->
</small>
<div class="entry">
<?php the_content('Read the rest of this entry »'); ?>
</div>
<p class="postmetadata"><?php the_tags('Tags: ', ', ', '<br />'); ?>
Posted in <?php the_category(', ') ?> |
<?php edit_post_link('Edit', '', ' | '); ?>
<?php comments_popup_link('No Comments »',
'1 Comment »', '% Comments »'); ?>
</p>
</div>
<?php endwhile; ?>
Here’s what my above post looked like with the above template code:

Other templates like single.php and archive.php in the Default theme have very similar code where you can also insert the thumbnail. Your theme may differ, but usage is very simple. Just call the following function in your template wherever you want to display the thumbnail:
<?php echo get_post_thumbnail(get_the_ID()); ?>
There has been much discussion about a recent bug/issue with Wordpress that prevents scheduled posts from working properly. The problem is somewhat unrelated to Wordpress itself, and is primarily a hosting setup issue. Scheduled posts are published via the use of a cron script. Wordpress attempts to call the cron script with an fsockopen() function call. Many popular hosts disable the use of fopen() in their PHP configuration, which also disables the fsockopen() function, preventing your cron from firing which prevents your scheduled posts from being published.
A more robust way of programming this part of the code would be to try other functions like curl on failure of the original fsockopen() call. If curl is unavailable, then the calling script should just execute the code contained within the wp-cron.php file itself, instead of trying to make an http request to execute it.
I’ve put together a simple fix for sites that cannot use the fsockopen() function. It’s a simple addition, and just requires attention when upgrading. Steps for upgrading are detailed below the fix.
Open up your wp-cron.php file and copy the contents following the “if ( $_GET['check'] != wp_hash(’187425′) ) exit;” line.
Now you are going to have to paste these lines at the very end of the spawn_cron() function in wp-includes/cron.php. After pasting them in you are going to have to change the “if ( $argyle )” clause to be an if/else clause. This will cause the else clause to execute when fsockopen() fails.
In Wordpress 2.6.3, the spawn_cron() function within the wp-includes/cron.php file will now look like this:
function spawn_cron() {
$crons = _get_cron_array();
if ( !is_array($crons) )
return;
$keys = array_keys( $crons );
if ( array_shift( $keys ) > time() )
return;
$cron_url = get_option( 'siteurl' ) . '/wp-cron.php';
$parts = parse_url( $cron_url );
if ($parts['scheme'] == 'https') {
// support for SSL was added in 4.3.0
if (version_compare(phpversion(), '4.3.0', '>=') && function_exists('openssl_open')) {
$port = isset($parts['port']) ? $parts['port'] : 443;
$argyle = @fsockopen('ssl://' . $parts['host'], $port, $errno, $errstr, 0.01);
} else {
return false;
}
} else {
$port = isset($parts['port']) ? $parts['port'] : 80;
$argyle = @ fsockopen( $parts['host'], $port, $errno, $errstr, 0.01 );
}
if ( $argyle ) {
fputs( $argyle,
"GET {$parts['path']}?check=" . wp_hash('187425') . " HTTP/1.0\r\n"
. "Host: {$_SERVER['HTTP_HOST']}\r\n\r\n"
);
}
else {
//BEGIN COPIED wp-cron.php CONTENTS
if ( get_option('doing_cron') > time() )
exit;
update_option('doing_cron', time() + 30);
$crons = _get_cron_array();
$keys = array_keys($crons);
if (!is_array($crons) || $keys[0] > time())
return;
foreach ($crons as $timestamp => $cronhooks) {
if ($timestamp > time()) break;
foreach ($cronhooks as $hook => $keys) {
foreach ($keys as $key => $args) {
$schedule = $args['schedule'];
if ($schedule != false) {
$new_args = array($timestamp, $schedule, $hook, $args['args']);
call_user_func_array('wp_reschedule_event', $new_args);
}
wp_unschedule_event($timestamp, $hook, $args['args']);
do_action_ref_array($hook, $args['args']);
}
}
}
update_option('doing_cron', 0);
//END COPIED wp-cron.php CONTENTS
}
}
Upgrading
It is very important to remember that you’ll have to take special precautions when upgrading. When upgrading, you are going to have to perform the same copy/paste and alter within the wp-includes/cron.php file. Take whatever the contents of the wp-cron.php file are and copy them after the above mentioned hash check line.
Wordpress’s dynamically generated feeds is one of its strongest points. However, there is a glaring omission with the feed generation code – there is no way to generate a feed by tag. Through work, I have been in several situations where creating a feed by tag is a product requirement.
With a small core mod, you can change your Wordpress blog to provide feeds by tag. Note: modifying core files has some ramifications. Mainly, the next time you upgrade your Wordpress instance, you must also merge in and upgrade all your core modifications. It’s important to keep core mods simple and well documented, so you’ll remember to do it again months down the line.
To add an RSS feed by tag, simply add the following lines to the top of your /wp-includes/feed-rss.php file AFTER the php header() function call.
$tag = (urldecode($_GET['tag']));
if (!empty($tag)) {
query_posts("tag=$tag");
}
Within the broader context of the file, the code will look like this:
<?php
/**
* RSS 0.92 Feed Template for displaying RSS 0.92 Posts feed.
*
* @package WordPress
*/
header('Content-Type: text/xml; charset=' . get_option('blog_charset'), true);
$more = 1;
/* CORE MOD - Added feed by tag */
$tag = (urldecode($_GET['tag']));
if (!empty($tag)) {
query_posts("tag=$tag");
}
?>
<?php echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; ?>
Now, you’ll be able to add links to RSS feeds by tags in these formats:
http://www.mysite.com/feed/?tag=politics
http://www.mysite.com/feed/rss/?tag=politics
Easy, right?
|