If you’ve worked on any projects as a web developer in the past few years, chances are that what you worked on relied rather heavily on JavaScript and AJAX. And chances are that you discovered, just as I did, that, in addition to all of the CSS headaches you have to deal with when developing for IE, you’ve got a whole slew of IE-related JavaScript headaches, as well. Even leaving aside the little IE-only DOM quirks, you’ve got a big problem still: IE’s flat-out terrible JS performance.
I mean it. Terrible. On one of my most recent projects at work, a Java-based, heavily JS & AJAX-reliant web-application, we discovered that our page load times in IE were anywhere between two to ten (!) times as long as those in Firefox. Which was, obviously, unacceptable, especially given the fact that the app’s user-base is comprised almost entirely of IE6/Win users. So what was I to do? Optimize, of course.
On my quest to find how to optimize my JS to run faster in IE, I came across these great articles, straight from the horse’s mouth, on how to do it:
Unfortunately, while they were certainly illuminating, these articles didn’t do much to solve my problem. Their recommendations, such as caching DOM lookups, weren’t much help to me when I only needed to do those lookups once.
After that, I thought briefly that part of the reason the page controls were taking so long to become available was that the onload event was being delayed due to images loading on my page, thereby causing an overall delay in total page-load time. And I found this nifty method to kick off window.onload after the DOM has loaded, but before other things like images finish loading.
As it happened, though, that didn’t make a bit of difference with my particular issue. What was causing the problem—as I found out after using the brute-force method to comment out all the code in the offending JS function, then adding it back in line by line to see what broke the performance camel’s back—was that using Prototype‘s built-in getElementsByClassName function was doubling, or tripling, or worse, IE page-load times. Especially since I called it in 2 or 3 different functions, all of which ran at window.onload.
So I needed to get (or, god forbid, write) an optimized getElementsByClassName function. Luckily, though, I was spared that horrible fate, because I found the Ultimate getElementsByClassName, courtesy of a guy by the name of Robert Nyman. In a fit of desperation, I added this to my JS library and changed all my code to call it instead of Prototype’s version. Et voilà: just from that one change, I had quadrupled (quadrupled!) my JS performance in IE. Pretty amazing.
Update 2007/10/24 1453: I recently ran into a similar problem again, where page load times, particularly for large pages, were up to 10 times slower in Safari than Firefox, and 20 or more times in IE. The problem was eventually traced back to the use of the Prototype double-$ lookup for CSS-style selectors. The solution? Just don’t use it. It might take more code to find the item you’re looking for, but the performance gain you get from not using the $$ lookup is worth it.