jQuery 3.0 Release Candidate…Released!

May 20th, 2016

Welcome to the Release Candidate for jQuery 3.0! This is the same code we expect to release as the final version of jQuery 3.0 (pending any major bugs or regressions). When released, jQuery 3.0 will become the only version of jQuery. The 1.12 and 2.2 branches will continue to receive critical support patches for a while, but will not get any new features or major revisions. Note that jQuery 3.0 will not support IE6-8. If you need IE6-8 support, you can continue to use the latest 1.12 release.

Despite the 3.0 version number, we anticipate that these releases shouldn’t be too much trouble when it comes to upgrading existing code. Yes, there are a few “breaking changes” that justified the major version bump, but we’re hopeful the breakage doesn’t actually affect that many people.

To assist with upgrading, we have a brand new 3.0 Upgrade Guide. And the jQuery Migrate 3.0-rc plugin will help you to identify compatibility issues in your code. Your feedback on the changes will help us greatly, so please try it out on your existing code and plugins!

You can get the files from the jQuery CDN, or link to them directly:

You can also get the release candidate from npm:

npm install jquery@3.0.0-rc1

In addition, we’ve got the release candidate for jQuery Migrate 3.0. We highly recommend using this to address any issues with breaking changes in jQuery 3.0. You can get those files here:

npm install jquery-migrate@3.0.0-rc1

For more information about upgrading your jQuery 1.x and 2.x pages to jQuery 3.0 with the help of jQuery Migrate, see yesterday’s jQuery Migrate blog post.

Major changes

Below are just the highlights of the major new features, improvements, and bug fixes in these releases, you can dig into more detail on the 3.0 Upgrade Guide. A complete list of issues fixed is available on our GitHub bug tracker.

jQuery.Deferred is now Promises/A+ compatible

jQuery.Deferred objects have been updated for compatibility with Promises/A+ and ES2015 Promises, verified with the Promises/A+ Compliance Test Suite. This meant we needed some major changes to the .then() method:

  • An exception thrown in a .then() callback now becomes a rejection value. Previously, exceptions bubbled all the way up, aborting callback execution and irreversibly locking both the parent and child Deferred objects.
  • The resolution state of a Deferred created by .then() is now controlled by its callbacks—exceptions become rejection values and non-thenable returns become fulfillment values. Previously, returns from rejection handlers became rejection values.
  • Callbacks are always invoked asynchronously. Previously, they would be called immediately upon binding or resolution, whichever came last.

Consider the following, in which a parent Deferred is rejected and a child callback generates an exception:

var parent = jQuery.Deferred();
var child = parent.then( null, function() {
  return "bar";
var callback = function( state ) {
  return function( value ) {
    console.log( state, value );
    throw new Error( "baz" );
var grandchildren = [
  child.then( callback( "fulfilled" ), callback( "rejected" ) ),
  child.then( callback( "fulfilled" ), callback( "rejected" ) )
parent.reject( "foo" );
console.log( "parent resolved" );

As of jQuery 3.0, this will log “parent resolved” before invoking any callback, each child callback will then log “fulfilled bar”, and the grandchildren will be rejected with Error “baz”. In previous versions, this would log “rejected bar” (the child Deferred having been rejected instead of fulfilled) once and then immediately terminate with uncaught Error “baz” (“parent resolved” not being logged and the grandchildren remaining unresolved).

While caught exceptions had advantages for in-browser debugging, it is far more declarative (i.e. explicit) to handle them with rejection callbacks. Keep in mind that this places the responsibility on you to always add at least one rejection callback when working with promises. Otherwise, any errors will go unnoticed.

Legacy behavior can be recovered by replacing use of .then() with the now-deprecated .pipe() method (which has an identical signature).

We’ve also built a plugin to help in debugging Promises/A+ compatible Deferreds. If you are not seeing enough information about an error on the console to determine its source, check out the jQuery Deferred Reporter Plugin.

jQuery.when has also been updated to accept any thenable object, which includes native Promise objects.

Added .catch() to Deferreds

The catch() method was added to promise objects as an alias for .then(null, fn).

Error cases don’t silently fail

Perhaps in a profound moment you’ve wondered, “What is the offset of a window?” Then you probably realized that is a crazy question – how can a window even have an offset?

In the past, jQuery has sometimes tried to make cases like this return something rather than having them throw errors. In this particular case of asking for the offset of a window, the answer up to now has been { top: 0, left: 0 } With jQuery 3.0, such cases will throw errors so that crazy requests aren’t silently ignored. Please try out this release and see if there is any code out there depending on jQuery to mask problems with invalid inputs.

Removed deprecated event aliases

.load, .unload, and .error, deprecated since jQuery 1.8, are no more. Use .on() to register listeners.

Animations now use requestAnimationFrame

On platforms that support the requestAnimationFrame API, which is pretty much everywhere but IE9 and Android<4.4, jQuery will now use that API when performing animations. This should result in animations that are smoother and use less CPU time – and save battery as well on mobile devices.

jQuery tried using requestAnimationFrame a few years back but there were serious compatibility issues with existing code so we had to back it out. We think we’ve beaten most of those issues by suspending animations while a browser tab is out of view. Still, any code that depends on animations to always run in nearly real-time is making an unrealistic assumption.

Massive speedups for some jQuery custom selectors

Thanks to some detective work by Paul Irish at Google, we identified some cases where we could skip a bunch of extra work when custom selectors like :visible are used many times in the same document. That particular case is up to 17 times faster now!

Keep in mind that even with this improvement, selectors like :visible and :hidden can be expensive because they depend on the browser to determine whether elements are actually displaying on the page. That may require, in the worst case, a complete recalculation of CSS styles and page layout! While we don’t discourage their use in most cases, we recommend testing your pages to determine if these selectors are causing performance issues.

This change actually made it into 1.12/2.2, but we wanted to reiterate it for jQuery 3.0.

As mentioned above, the Upgrade Guide is now available for anyone ready to try out this release. Aside from being helpful in upgrading, it also lists more of the notable changes.