Load JQuery from Google’s CDN with local fallback in WordPress

Posted on by Chris

The advantages of loading scripts from Google’s CDN are fairly obvious – for a common script such as jQuery, we’re on to a better-than-even chance that the user will already have the script in their browser’s cache from other sites, reducing the total download weight of your site. Even if they don’t, the file will be downloaded from their nearest Google CDN server, which will still be faster than downloading it from your site because it will be downloading in parallel from a different host.

Including jQuery in WordPress the Right Way™

A fairly common technique in WordPress is to include jQuery in the footer with wp_enqueue_script(), like so:

function rd_include_jquery() {
    wp_deregister_script('jquery');
    wp_register_script('jquery', 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js', false, false, true);
    wp_enqueue_script('jquery');
}
add_action('wp_enqueue_scripts', 'rd_include_jquery');

But what happens on the rare occasions where Google’s CDN is down or unreachable? Maybe they’re having technical problems, or you’re working offline, or any number of things which could get between your site and Google’s CDN. HTML5 Boilerplate has a great workaround for this, which immediately follows the jQuery load with the following:

<script type="text/javascript">window.jQuery || document.write('<script src="js/libs/jquery-1.5.1.min.js">\x3C/script>')</script>

Because this method relies on writing the script element directly to the page after the jQuery call, it would seem to be totally incompatible with wp_enqueue_script. Don’t worry, you don’t have to revert to manually writing out script calls in your header or footer. Here’s what we’re going to do:

Including jQuery in WordPress the Right Way™ (the Turbocharged, Bulletproof Local Fallback Edition)

First, we need to solve the problem of determining if Google’s CDN is accessible, which we’ll do with wp_remote_head(). Assuming that’s available, we’ll cache the HTTP response using the WP Transients API to avoid having to make the same request every time a page is loaded – the right value for the transient’s $expiration value will depend on the traffic of the site, but for the sake of demonstration let’s set it to 5 minutes.

function rd_bulletproof_jquery() {
$protocol = ($_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
$url = $protocol . '://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';
wp_deregister_script('jquery');
if (get_transient('google_jquery') == true) {	    
	wp_register_script('jquery', $url, array(), null, true);
} 
else {
	$resp = wp_remote_head($url);
	if (!is_wp_error($resp) &amp;&amp; 200 == $resp['response']['code']) {
		set_transient('google_jquery', true, 60 * 5);
		wp_register_script('jquery', $url, array(), null, true);
	} 
	else {
		set_transient('google_jquery', false, 60 * 5);
		$url = get_bloginfo('wpurl') . '/wp-includes/js/jquery/jquery.js';
		wp_register_script('jquery', $url, array(), '1.7.1', true);
	}
}
wp_enqueue_script('jquery');
/* Any other Javascript would be enqueued here */
}
add_action('wp_enqueue_scripts', 'rd_bulletproof_jquery');

Credits: based on the work of Christopher Davis, and modified to use a protocol-less URL thanks to a comment by Sam.

This entry was posted in WordPress and tagged , , , . Bookmark the permalink.

Leave a Reply

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