Building a Slimmer jQuery

Posted on by

jQuery is more than five years old now! Over that time it has evolved along with the browsers, web sites, devices, developers, and users that it serves. It has also, um, grown quite a bit over that time. jQuery has added a lot of useful features, but it’s also accumulated cruft that we’d prefer not to support into perpetuity. It may not be an issue on a desktop PC with a high-speed connection, but we want jQuery to be a good solution for mobile devices as well.

Along with our continuing push for higher performance, our priority for upcoming versions is a smaller gzipped file size. It’s hard to do that when every new feature or bug fix must also preserve all existing features and behavior. So today, we want to start a conversation about slimming down the jQuery API by deprecating some features. Here are our guidelines for deprecation:

  • We don’t believe the feature represents current best practice in the use of jQuery.
  • The feature has proven unpopular, confusing, inefficient, or ineffective in actual use.
  • It is not practical or feasible to enhance the feature or address its limitations.
  • Removing it at some future time could yield notable usability, size, or performance benefits.

Deprecation is just the first step in a process that you can participate in. It is our goal to:

  • Explain the reasons for deprecating a particular feature, as described above.
  • Give at least one major-point-version, and often more, between deprecation and removal.
  • Provide alternatives to deprecated features so that migration is not painful.
  • Listen to community feedback regarding deprecation and removal.

Occasionally, as in the situation with event.layerX/layerY in version 1.7, we will make a breaking change with shorter notice if we judge that it will cause less pain to remove the feature immediately than to leave it in. Those will hopefully be rare exceptions.

Version 1.7 Deprecations

With those things in mind, we consider the following features to be deprecated as of version 1.7. Existing code that uses them continues to work, but the recommended alternatives are a better choice for compatibility with future versions.

.live() and .die(): We continue to get many bug reports and see user confusion regarding the quirks of the .live() method. Common issues are now documented on its updated API page. We strongly advise the use of .on() or .delegate() for new code, since they are better APIs. Given its widespread use it’s unlikely we will remove this API in 1.8, but please do update your code as soon as possible.

Non-standard event properties: As part of our push to improve event handler performance, we are also deprecating the copying of several event properties from the native event object to the jQuery event object and will remove them in 1.8: attrChange, attrName, relatedNode, and srcElement. Instead of accessing these through event.NAME you can access them via event.originalEvent.NAME where needed.

$.ajax() Deferred aliases: In version 1.5 we defined .error()/,success()/.complete() on the jqXHR object as aliases for the Deferred’s .fail()/.done()/.always() methods. Although that seemed like a good idea at the time, it makes jqXHR a non-standard Deferred. That’s not good. Whenever possible, use the deferred/promise method name in preference to the jqXHR one. We still have some work to do here to provide a full migration path, so we are likely to continue supporting the aliases past 1.8.

deferred.isResolved() and deferred.isRejected(): Now that Deferreds and Promises have progress notifications and a convenient .state() method, we are deprecating these older methods and will remove them in 1.8. Getting the state of an N-state object using N-1 Boolean methods is a cruel-code version of “Twenty Questions”. Deferred-based code rarely needs to inspect state, and the string returned now is more convenient for a debugging scenario where it’s often used.

.attr(“value”) on inputs: For backwards compatibility, we’ve been returning the current value here (as in “what is currently in the input box”) versus the real attribute (what the value attribute says in the HTML). That leaves us no way to provide the true attribute value, and is confusing since W3C selectors work on the attribute and not the current value. So we are deprecating this behavior and will remove it in 1.8. Always use the .val() method to get the current live value of an input element. Until we can reclaim the attribute, you can use $("selector")[0].getAttribute("value") except on IE 6/7 where that will still return the current value. (Our 1.8 solution will get the attribute value on all browsers and is another reason why we’re anxious to change this.)

.closest(Array) returning Array: This signature is a bit of a strange bird, it was created for use by the old live events code but it returns an Array rather than a jQuery object. As of 1.8 we plan to remove it. The other signatures of .closest() are here to stay and are not affected.

.data(“events”): jQuery stores its event-related data in a data object named (wait for it) events on each element. This is an internal data structure so in 1.8 this will be removed from the user data name space so it won’t conflict with items of the same name. jQuery’s event data can still be accessed via jQuery._data(element, "events") but be aware that this is an internal data structure that is undocumented and should not be modified.

$.sub() as a plugin: Although $.sub() can be useful for creating interference-free zones for plugins, it is not used by jQuery core and not widely used by other code, so we intend to transition it to a plugin in version 1.8 to save space.

Looking Towards jQuery 1.8

Given our push for a svelte jQuery, the filter for new features in 1.8 will be stringent. Even performance-related proposals need to be balanced against the space they use or save. Features that can be implemented via plugins, special events, attribute hooks, or other jQuery extension mechanisms are likely to stay outside core for now.

That brings up the question of what we could deprecate in 1.8 and eventually remove to simplify and streamline the library. Those things don’t have to totally disappear; they could move into a separate plugin, for example, and only be included when needed. Take a look at how you use jQuery, and talk about it with your colleagues.

Within a few weeks, we’ll be opening the call for your ideas concerning jQuery 1.8 with another blog post — so start thinking about it now!

Edit: No, we’re not removing IE6 support yet, and we can’t. As John Resig mentions at every jQuery Conference, most of the sins of IE6 are also visited upon IE7 and IE8, which together still have more than one-third of desktop browser market share. It doesn’t make sense to remove support for IE6 until we can whack IE7 and IE8 as well.

113 thoughts on “Building a Slimmer jQuery

  1. Do what modernizer does, make the core of jQuery really lean, then allow us to select different capabilities/plugins to add to the package that would be combined into a custom jquery js file. jQuery is absolutely laughable on mobile, I tried it out, and even the official demos are a joke… The animation stutters and it’s jagged… no one could possibly use jquery mobile and be satisfied…

  2. I agree that having ie 6/7/8 compatibility as a plugin or different build would be huge for us.

    Some of our apps are mainstream, and we need cross-browser support, as much as we hate it.
    But for some other projects, we have a tech crowd that greatly appreciate fast loading apps with modern browsers.

    That simple feature would turn me into a definite advocate of jQuery, for its implication toward a better web. Entire sets of economics sort of depend on this kind of choices. You can really make a difference here.

  3. browndog on said:

    Deprecation and removal is not the solution to any problem it only creates new problems. Modularize if you must but never remove. I can understand if someone is using jquery on a small site or page having breaking changes from one version to another is no big deal, but how about a large scale implementation with hundreds if not thousands of individual pages that use a common header to set which js files get included? If you have a large deployed site any breaking changes requires work to fix breaking changes then requires massive amount of testing to re-certify and re-deploy the new version (user acceptance testing is always the mother load of the work).

    Also features aren’t the only reason people move to new versions, there is bug fixes and performance improvements as well. Add to this SOX/Audit requirements that all production code be fully supported by vendors and be of current version/bug fix/security fix level. Decisions like this means there is a massive liability that a site takes on when they choose to use a framework. I think you run great risk of losing large developer support if every six months you introduce breaking changes.

    For example with the removal of .live(), why remove it why not keep the function but just make it a helper function for .on()? So that you take the parameters of the live function and make a call to .on() with the passed parameters. I think introducing breaking changes is a greater evil then adding a couple kb to the overall size of the download. Remember bandwidth and computing power is always increasing. And I can always using jquery mobile for mobile devices.

  4. Hardcore on said:

    Microsoft has already stated that IE6 is DEAD, it is an E.O.L product with no support.
    Continuing to support dead products is a drain on the developer resources.
    Since all new functions added to the library need to ensure they do not break any existing functionality, this requires testing resources to be diverted away from more important tasks.

    Pin the library at <2.0 for IE6 support, then start the new library without IE6 at 2.0.
    Consider also the fact that millions of KB of bandwidth are being wasted worldwide for jQuery supporting IE6 when it is not needed.

  5. jQuery 2 IMHO should:

    1. Support just HTML5/CSS3/JS1.9
    2. Advocate ChromeFrame for our poor IE users (it is time to say, IE10 or bye, bye IE so that we can really innovate)
    3. Use AMD for modular support

    I’m now advocating the above 3 points for our enterprise customers and I feel that jQuery in its current form will become less relevant given such an environment.

  6. I have to second the strong desire for a modular jQuery, or at least a version of jQuery without legacy IE support…

    While I understand the desire for it in some web based applications, there are equally as many applications where people don’t want to support IE, and worse don’t want the bloat associated with it – to the point where people have started making alternatives to jQuery just to serve this purpose already…

    Would be so much nicer of jQuery could just step up and take charge of the situation & provide options for people instead of alienating a growing user base and moving development efforts elsewhere.

  7. +1 for modularization. developers should be able to decide for themselves which parts of the library they and which not, e.g. the whole ajax block. 91k for the minified, un-gzipped version isn’t all too neat.

  8. “Please don’t drop IE6 yet! It’s still important to some projects. Give it at least one more year!”

    If you need IE6 support, just use an older version of jQuery. There is no need for versions 1.8+ to have special support for IE6. I’m sure some super excited developer working on a corporate intranet portal site will be motivated enough to build a IE6 plugin that is compatible with 1.8+, or be smart enough to just not use 1.8+

  9. I don’t understand why some people are so concerned about removing/deprecating features. If you need those features, simply use / stick with an older version of jquery. If it worked fine on your site then, it will work fine on it now. It makes absolutely not logical sense to upgrade to a newer version if you are still developing for and supporting an older site designed to run on older browsers. This is a moot argument.

  10. Old thread, I know… But I’m for it.

    Don’t need it modular per se, but it would be nice to have includes along the line of: