Easily Test jQuery Pre-Release Versions


Get the complete code on github.

It’s always exciting when a new major jQuery version (x.x.0) full of bug fixes, new features and performance improvements is released. But that fresh, out of the box excitement can get replaced with anxiety if you find bugs or performance issues with the latest version. This post will cover a way to include jQuery while provide a way to test pre-release versions of jQuery.

When a major version of jQuery is being developed, far too few developers actually test the beta and release-candidate (RC) versions inside of their applications. This can be challenging for those putting time and effort into a steady beta and RC release schedule, and those expecting a bullet-proof version of jQuery upon release. While there are over 6000 unit-tests for jQuery, as well as manual testing done by the core and bugs team, it’s not always enough to find new bugs or possible performance hits in user-land code. The result is a major release landing, everyone downloading and upgrading in a frenzy, and that needed testing from the community happening on a full-fledged release. Thus, the x.x.1 release is right on the tails of x.x.0. This problem is not as bad on subsequent point-releases, since they are only include bug fixes, but it still happens.

What’s the solution? Help test the latest versions, of course! This is as simple as replacing the stable version of jQuery in your application with the latest beta or RC, and making sure everything still works right – or if it doesn’t, letting the jQuery project know what broke and how.

Unfortunately, manually adding in the latest version of jQuery to your site, even in a staging environment, can be a hassle. We can improve this situation by implementing a switch that lets us use a stable version of jQuery by default, while allowing a different jQuery version to be loaded for testing just by specifying a version number in the URL.

An easy way to specify a particular version of jQuery on a page would be a query string argument, such as jqversion=1.7.0rc1. We can use a simple regular expression to get that out of the search property of the location object (the object that holds all the information about the uri the page is currently on).

gistfile1.js

var version = verMatch && verMatch[1];

This looks for jqversion= followed by any digits, letters, or periods. By limiting the match to only those characters, possible XSS vulnerabilities are avoided, such as someone entering jqversion="><script src="http://hax.com/someScript.js"><\/script> in the URL. If the regular expression matches, verMatch will be an array of the original search text and the match, e.g., [ 'jqversion=1.7rc2', '1.7rc2' ]. Let’s put that into a variable:

gistfile1.js

var version = verMatch && verMatch[1];

We’re using short-circuit evaluation here. First, verMatch is evaluated. If it’s falsy, it will stop evaluating and assign that falsy value of verMatch to version. If it’s truthy (i.e., if there was a match with the regular expression) the expression will continue on and evaluate verMatch[1]. The resulting version variable is either verMatch being equal to null (a falsy value meaning there was no match) or verMatch[1], the matched version number from the URL (a truthy value). Checking for verMatch before assuming that verMatch[1] exists is essential. If the regular expression didn’t match, an error would be thrown when attempting to access the 2nd element on a null object.

If a version was specified in the url, we now have that stored in the version variable. To use that version information to make a script tag pointing to the correct file, we can use document.write:

gistfile1.js

document.write( '<script src=\"//code.jquery.com/jquery-' + version + '.js\"><\\/script>' );

This writes the script tag pointing to the un-minified copy of the jQuery version specified immediately after the script tag this code is currently executing in.

While having the un-minified copy of jQuery is helpful for debugging, it’s recommended to use a minified copy in production. Also, here at Bocoup, we like to use Google’s CDN since they have more servers, higher speeds and more saturation (more possibility of a cached copy). If a version is specified, the jQuery CDN with an un-minified copy should be used. If a version isn’t specified, the Google CDN with a minified copy should be used.

gistfile1.txt

var verMatch = /jqversion=([\w\.]+)/.exec( location.search ),
    version = verMatch && verMatch[1];
if ( version ) {
  document.write( '<script src="//code.jquery.com/jquery-' + version + '.js"><\/script>' );
} else {
  document.write( '<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"><\/script>' );
}

Now this is starting to take shape. However, making the verMatch and version variables global is unnecessary. And it would be nice to have some kind of local copy of jQuery if Google’s CDN has any issues serving the file. The multiple document.write calls don’t seem very DRY, either.

Here’s the final version that can replace the typical <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> tag used to include jQuery on a webpage.

snippet.htm

<script>
  (function(){
    // Look for a jqversion query parameter and grab any following version.
    // Limit to digits and letters to prevent any XSS attempts
    var verMatch = /jqversion=([\w\.]+)/.exec( location.search ),
        // our matched version, e.g., 1.6.4 or 1.7rc1
        version = verMatch &amp;&amp; verMatch[1],
        src;
    if ( version ) {
      // version was specified, use jQuery's CDN to acccess non-mininfied betas and RCs
      src = 'code.jquery.com/jquery-' + version;
    } else {
      // nothing was specified, use the Google CDN (or jQuery's or Microsoft's) with a minified copy
      src = 'ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min';
    }
    // create the script tag
    document.write( '<script src="//' + src + '.js"><\/script>' );
  })();
</script>
<script>
  // Use a local copy, incase the above didn't load
  if ( !window.jQuery ) {
    document.write( '<script src="/scripts/jquery-1.7.0.min.js"><\/script>' );
  }
</script>

By default, the page will load a minified version of jQuery from the Google CDN. If that doesn’t work, it will load a local copy of jQuery. If jqversion=, followed by the version tag, is in the URL it will attempt to download that from the jQuery CDN. For example, jqversion=1.7, jqversion=1.7rc1, or jqversion=1.4.4. The whole code block is wrapped in an IIFE to keep the variable’s scope to just that function. The local jQuery fallback code goes in another script tag. Since we’re injecting a script tag using document.write, it won’t download and load before the check for window.jQuery runs if it’s in the same script tag.

If the main html of a page isn’t minified, you might prefer to remove the comments to reduce the size of your html file. For minifying javascript, Uglify.js is a great javascript minifier that’s easy to use. Here is what the final code looks like when ran through uglify.js:

gistfile1.html

<script>(function(){var a=/jqversion=([\d\w\.]+)/.exec(location.search),b=a&&a[1],c;if(b){c="code.jquery.com/jquery-"+b}else{c="ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min"}document.write('<script src="//'+c+'.js"><\/script>')})()</script>
<script>window.jQuery||document.write('<script src="/scripts/jquery-1.7.0.min.js"><\/script>' )</script>

In both code snippets, you can replace the 1.7.1 in the googleapis.com URL to whatever version you want to have on your page, such as, 1.6.4 or 1.5.2. Also, be sure to update the path pointing to your local jQuery copy in the second script tag.

You can also test the latest development copy by using git as your version, e.g., jqversion=git. If you’d like to see what version of jQuery is currently loaded on a page, that is stored in the jquery property on jQuery’s prototype at $.fn.jquery and thus as the jquery property on any jQuery object, e.g., $( document ).jquery.

Keeping Up And Helping Out

Follow along with the jQuery Blog to see when betas and release-candidates are released. Testing will be a piece of cake with this new jQuery include process. For example, when the 1.8.0 release-candidate is out, a url like http://yoursite.com/?jqversion=1.8.0rc1 will let you load your site with that version of jQuery. Found a bug? Report it on the jQuery bug tracker. Want to chat with the development team? Head into #jquery-dev on irc.freenode.net. Filed a bug and already fixed it? Submit a pull request on github. Spending even a little bit of time testing your sites with the in-development copies of jQuery can help significantly in assisting the project to finding bugs before final releases are made. Happy testing!

Comments

Contact Us

We'd love to hear from you. Get in touch!

Phone

+1 617-283-2807

Mail

P.O. Box 961436
Boston, MA 02196