jQuery Library Size
exploring jQuery’s role in web page weight
In this post, I look at how jQuery has changed in size over recent versions. I also look at custom builds and how much each unused feature adds to your page weight.
Note: this article was updated 2014-03-06, check below the conclusion
recent jQuery versions
jQuery 2 drops support for browsers that are missing ECMAScript 5,
addEventListener (e.g. Internet Explorer 8 and older).
In order to continue supporting such browsers, jQuery 1.10 continues to be
developed in parallel.
The following table shows the version numbers for the parallel releases:
page weight between releases
After checking out the jQuery source code, I ran the following shell commands to automate building the above versions:
for tag in 1.10.0 1.10.1 1.10.2 1.11.0 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 do rm -fr src/sizzle test/qunit dist/* git checkout $tag npm install grunt done
The following tables shows the sizes (in bytes) for the development build of jQuery (including comments, etc):
The following tables shows the sizes (in bytes) for the production build of jQuery (optimised and minified):
impact on page weight
The easiest version for humans to read is the raw development build, which is constructed by joining all the individual source code files together. Thus, we can see that the additional source code to support old versions of Internet Explorer is between 31KB and 38KB.
This legible code is then optimised for production use, typically stripping white space and comments, renaming variables and safely re-ordering code. Further, almost all web browsers request the GZIP-compressed version of this optimised code, reducing the size of the download significantly.
So, in practice, supporting old versions of Internet Explorer with jQuery only adds between 3.5KB and 4KB to our page weight.
Note: this comparison does not examine the memory usage or possible performance impact for the extra code, only the impact on network usage.
For several releases now, it has been possible to customise jQuery’s build process so that it only includes the pieces that you want. How this is achieved is documented here.
modules I keep
event: this jQuery feature allows us to bind event handlers just once on
document.body, which simplifies our code and saves memory
exports/global and exports/amd: these don’t take up much space and just make including jQuery in both sorts of projects that much easier
sizzle: I only need this in my 1.x compatibility build, because this enables jQuery to function without
querySelector(which is missing in old browsers)
css, dimensions and offset: these make working with DOM elements and their styles a breeze, some of which still isn’t as easy without jQuery
modules I exclude
deprecated: I don’t use deprecated features, so I don’t need them
event/alias: I prefer
.wrap()methods can be quite handy, but I my use of templates and data binding tends to limit their usefulness
sizzle: I can remove this from the 2.x modern build, because I avoid using jQuery’s non-W3C CSS selectors (for performance reasons)
- css/hiddenVisibleSelectors and effects/animatedSelector: removed from the 1.x build for parity with 2.x
deferred: these aren’t Promises/A+ compliant
ajax: using this module is an exercise in frustration for me even when I need to support ancient browsers
core/ready: putting your
scriptelements at the end of
bodyis an easy enough alternative, and is considered to be better practice anyway
effects: I tend to use CSS Animations and/or JS libraries with fancier features
git checkout 1.11.0 npm install grunt grunt custom:-deprecated,-event/alias,-wrap,-core/ready,-ajax,-effects,-deferred,-css/hiddenVisibleSelectors compare_size git checkout 2.1.0 npm install grunt grunt custom:-deprecated,-event/alias,-wrap,-core/ready,-ajax,-effects,-deferred,-sizzle compare_size
grunt custom:... lines, I will group the exclusions in batches where
the reduction isn’t likely to be very high, or where dependencies need to be
- A: deprecated, event/alias, and wrap
- B: ajax
- C: effects
- D: deferred, ajax, effects, core/ready
- E: sizzle for 2.x, css/hiddenVisibleSelectors and effects/animatedSelector for 1.x
- F: all of the above
For each of the above batches, the following table compares the sizes of the following:
- raw source code for the 1.x compatibility build
- raw source code for the 2.x modern build
- production minified and gzipped output for the 1.x build
- production minified and gzipped output for the 2.x build
The stock sizes (from the earlier comparisons) are repeated here for convenience.
|raw source||min + gzip|
impact on page weight
I’m happy to restrict my queries to W3C CSS (and not rely on the extra selectors added by Sizzle), so I exclude it from my 2.x build. As a result, we see my 2.x build drop 89KB of source code and 10KB of page weight with batch E.
jQuery vs custom jQuery
My production-optimised 1.x build is ~25% smaller than the full version, and my 2.x build is ~45% smaller. Those are huge savings, and could mean the difference between meeting a page weight budget and going over.
Even though you might not need jQuery in modern web browsers, I feel that jQuery still has much to offer. There are loads of bugs and browser quirks that jQuery handles for us.
jQuery offers easier event management compared to the standard DOM APIs. This
is very important for use cases that involve dynamic insertion of content and
binding events. For this,
addEventListener is still inadequate.
The APIs exposed by jQuery are well-understood and frequently emulated by other libraries like Angular.JS and Zepto. Developers should absolutely learn how to use the W3C DOM APIs, but jQuery’s are something of a standard, too.
Note: these are younger projects, and may not offer the same comprehensive bug fixes for browser quirks, or the same highly-tuned performance. I mention them here because you might care most of all about page weight, and these do beat jQuery on that score.
jQuery 2.x is smaller than 1.x, but not significantly so. You can widen the gap with a custom 2.x build that eschews Sizzle. I am a little disappointed that I wasn’t able to reduce it further.
A custom jQuery build such as mine could be used to enhance the selector
angular.element. Angular.JS provides its own cross-browser
AJAX and Promise functionality, which is wasted duplication with the complete
For new projects, you are probably better off starting without jQuery if you can help it. It is definitely a wasted download if you only perform basic DOM manipulation (or none at all).
For more complex needs, you should evaluate your options. Do you want to spend loads of time battling quirky browsers? Or would you rather use a library and have your users wait a bit longer?
Before removing Sizzle from jQuery the way I have here, you should read this discussion I had with a Sizzle developer.
querySelectorAll isn’t wired up to be a perfect replacement for
Sizzle, so you need to be aware of the differences.
There’s also a great quote here:
Measuring page weight is not the same as measuring load and render times. 100kb may in fact have a negligible effect on the performance of your page.