jQuery 2.0 Drops Old IE: How to Pick 1.x or 2.x
jQuery 2.0.0 came out last Thursday, April 18, and it’s the first jQuery release that won’t run on Internet Explorer 6, 7 or 8 at all. The jQuery team has been saying this was coming for almost a year, and it came with a plan: the 1.x line isn’t going away. So the real question is which of the two lines your site should load, and that depends on who actually shows up.
What 2.0 changed and why
The release announcement, jQuery 2.0 Released, lays out the trade. Leaving old IE behind makes the library smaller and faster, and it lets jQuery work in JavaScript environments where the old IE compatibility code tends to cause problems of its own. The team puts the final file at 12 percent smaller than 1.9.1, thanks to dropping patches that only IE 6, 7 and 8 needed. They’re also candid that they hoped to remove more code and gain more speed, but older Android 2.x WebKit browsers are now the weakest link, and they’re watching Android 2.x market share before crossing it off the list.
You can see what those old IE code paths look like by comparing the source at the two tags. In 1.9.1, the part of src/event.js that attaches a handler uses addEventListener when the element has it and falls back to IE’s own attachEvent when it doesn’t. In the 2.0.0 version of event.js that fallback is simply gone. Spread that kind of branch across events, attributes, feature detection and the rest of the library, and you get the size difference.
The other big feature is custom builds. You can now leave out combinations of 12 modules, and a new minimal selector engine, basically a thin wrapper around querySelectorAll, can get a build under 10KB minified and gzipped. The catch is that your plugins have to stick to the subset you kept, so for a typical website I’d ship the full file.
Where 2.0 is supported
The Browser Support page on jquery.com, as it read around the release, keeps it simple. jQuery 1.x supports Internet Explorer 6 and up, jQuery 2.x supports Internet Explorer 9 and up, and both support the current and previous versions of Chrome, Firefox, Safari and Opera.
There’s a trap hiding in “9 and up”. The announcement points out that IE9 and IE10 can behave like older versions when they run in Compatibility View, and that counts as old IE as far as 2.0 is concerned. The team suggests always sending an X-UA-Compatible meta tag or HTTP header so newer IE doesn’t slip back into an old mode, and says the header is slightly better for performance because it avoids a possible parser restart. The beta 3 post was even more direct: IE9 and IE10 have to run in their modern mode, not forced into IE7 mode.
The announcement also names environments where the team will no longer support 1.x because 2.x is a far better choice. They’re mostly places that aren’t websites at all, like Chrome add-ons and Firefox extensions, Firefox OS, Chrome OS and Windows 8 Store apps, PhoneGap/Cordova apps, embedded views like Apple’s UIWebView, and node.js with jsdom.
Same API, two code paths
What makes all this manageable is that both lines share one API. Back in June 2012, jQuery Core: Version 1.9 and Beyond set the goal of making 1.9 and 2.0 interchangeable in the APIs they support. The release post says 2.0 is API compatible with 1.9, which means every change in the jQuery 1.9 Upgrade Guide applies to 2.0 as well.
For what comes next, the team says it will ship jQuery 1.10 within a couple of months, pulling in the bug fixes and differences reported during the 1.9 and 2.0 beta cycles. After that it plans to keep feature parity in pairs, 1.10 with 2.0 and 1.11 with 2.1, while patch releases in each branch follow their own schedule. That’s an announced plan, not shipped code, so treat those version numbers as intentions.
Deciding based on who visits
The rule from that June 2012 post is still the clearest version. If you need IE 6, 7 or 8 support, choose 1.9, and otherwise you can use either one. The release post adds that the simplest way to support older browsers is to use 1.x on your site, since it works in all of them, and the team expects to support 1.x for several more years.
So the decision is about your visitors, and the place to find them is your own analytics rather than a global market share chart. My advice is to pull a browser and version report for a recent stretch of traffic and look at IE 6, 7 and 8 on their own. It’s worth checking the pages that matter most too, like checkout or signup, because a small share overall can still be a real share of the people who pay you. If that number is something you can’t give up, use 1.x and move on. If it’s close to zero, or your site already doesn’t work in those browsers for other reasons, 2.0 is a reasonable choice. And if you’re building an app, an extension or something that runs in node, the team is clearly pointing you at 2.x.
Serving both with conditional comments
There’s a middle path if you want 2.0 in modern browsers but still have old IE visitors. The release post calls it the conditional comment trick, points back to the beta 2 post for the details, and is careful to say it isn’t required. This is the pattern from the beta posts with the final version numbers:
<!--[if lt IE 9]>
<script src="jquery-1.9.1.js"></script>
<![endif]-->
<!--[if gte IE 9]><!-->
<script src="jquery-2.0.0.js"></script>
<!--<![endif]-->
Microsoft’s About Conditional Comments documentation explains why it works. The first block is what Microsoft calls a downlevel hidden conditional comment. Other browsers see an ordinary HTML comment and skip it, while IE only uses what’s inside when the expression is true, so IE 6, 7 and 8 get 1.9.1. The second block is written so the 2.0.0 script tag sits outside any comment for browsers that don’t understand conditional comments, and IE9 evaluates gte IE 9 as true and loads it too. IE10 is the interesting one. Microsoft’s page notes that as of IE10, conditional comments are no longer supported in standards mode, so IE10 treats both blocks as plain comments, which is exactly what you want here: it skips 1.9.1 and loads 2.0.0 like Chrome or Firefox would.
The cost is that your site now runs on two different builds depending on the browser, so every plugin and every page needs testing on both. If you aren’t going to do that, one file for everyone is the safer choice.
Test before you switch
If your code predates 1.9, the release post recommends the jQuery Migrate plugin along with the upgrade guide, since a lot changed in 1.9. You include it after jQuery and open the browser console to read its messages. The post’s own example looks like this:
<script src="http://code.jquery.com/jquery-2.0.0.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.1.1.js"></script>
The jQuery Migrate 1.1.1 README explains that the plugin can detect and restore APIs removed as of 1.9, that every warning starts with JQMIGRATE, and that the development version writes to the console while the minified production version stays quiet. It also says browsers without a console, like IE7, won’t show messages unless you add a debugging library, but you can inspect the jQuery.migrateWarnings array to see what was generated. I’d treat Migrate as a way to find what needs fixing rather than something to lean on forever.
Two more pieces of advice. First, run your key flows in each browser your analytics says matters, with the exact file you plan to ship. With conditional comments that means old IE on 1.9.1 and at least IE9, IE10 and a current Chrome or Firefox on 2.0.0. Second, pin the version. The release post says production sites should ask a CDN for a specific version, and that a loose URL like /2/ or jquery-latest.js is considered harmful to your site’s health and performance. If something works on 1.9.1 but breaks on 2.0.0, the team wants a minimal test case in its bug tracker, since keeping the two in step is the whole point.
The takeaway
jQuery 2.0 isn’t a forced upgrade. It’s a leaner build for audiences that have already left old IE behind, sitting next to a 1.x line the team says it will keep in step and support for years. Look at who really visits your site, pick the line that covers them, and because the API is shared, you can switch later without rewriting your code.