In most ways, the recent revelations about IE11 are amazing and awesome and I <3 <3 them. However, one particular side-effect of this announcement is very very unawesome. It's clearly a case of throwing the baby out with the bathwater.

IE11, PLEASE PLEASE re-consider your decision (as described in this blog post) and bring back “real script preloading”. PLEASE!

As @slicknet points out in “Internet Explorer 11: Don’t call me IE”, IE11 has eschewed many (all?) of their old non-standard APIs so that all the old “isIE” type “feature tests” (not really, but whatever) will fail, and IE11 should be served “standards-based” content.

This is a super understandable and admirable move on their part.

Preparations

So what’s the problem? One of these changes forces IE11 to take a big step backward in terms of performance/performance-flexibility with regards to script loading.

Put simply, if you want to dynamically load a bunch of scripts in parallel, but control their execution order (to ensure dependencies), the web platform doesn’t really give you very many options.

One option you have, which I call “ordered async”, was something I helped get added to the spec a couple of years ago. It amounts to setting script.async = false on dynamically created script elements. This tells the modern, spec-conforming browsers to load any/all such scripts in a parallel script loading queue, but to make sure their executions are in request-order, regardless of load completion.

In a lot of cases, this is sufficient. If you have just one grouping of scripts to load in parallel, and you want all of them to execute strictly in request-order, great. If, however, you need to load two or more separate groups of scripts (say “A-B-C” and “D-E-F”), where there’s no relationship between the two groups, and you want those groups to operate independently, you’re just SOL.

Or, if you want in your one grouping of scripts to have “A” and “B” run (in whatever-order), then “C”, then “D” and “E (in whatever order), you’re also out of luck.

Both of those use-cases will function fine with “ordered async”, but with less-than-optimal performance. There’s just one “ordered async” queue in the browser, and all your scripts that you do .async = false on will go into that queue, and will load in parallel but will strictly execute in request-order, meaning some executions may be delayed unnecessarily because you cannot express those more complex execution profiles with the web platform as it stands.

I’m glad we have “ordered async”, but I’m sad that we only have “ordered async”, because I quite often run across real-world scenarios where I need more control, and I don’t have it, so I just accept lower performance.

IE to the rescue!

Since IE4, however, there’s been a silver bullet for this problem. It’s the ultimate in performance-flexibility. I call it “real script preloading”. It’s superior (in terms of performance and performance-flexibility) to all other browsers, even today.

What this technique boils down to is being able to load many scripts in parallel, but allowing your code to be fully in control of what executes when, and in what order. You don’t have to rely on the browser’s “ordered async” queue semantics — your code has complete control. Performance++ and Flexibility++.

How it works is that IE (from version 4 to 10) will start loading (aka “preloading”) a script in the background, as soon as you set a src attribute on a dynamically created script element. However, that script may complete loading but will not execute until you actually insert that script element into the DOM.

So, you can “preload” any number of scripts, and then choose what order you want them to execute in by simply inserting them into the DOM as you see fit.

It’s amazing in its simplicity and power.

Before you assume this is just some proprietary non-standard thing IE does, consider this wording in the spec:

For performance reasons, user agents may start fetching the script as soon as the attribute is set, instead, in the hope that the element will be inserted into the document. Either way, once the element is inserted into the document, the load must have started. If the UA performs such prefetching, but the element is never inserted in the document, or the src attribute is dynamically changed, then the user agent will not execute the script, and the fetching process will have been effectively wasted.

But, this technique, to be effective, actually relies on something that is non-standard (as of yet), which is that to take advantage of on-demand-execution, you’ll need to be able to detect that the script has finished “preloading”.

No, the onload event doesn’t do that. Quixotically, script.onload doesn’t just mean “loaded”, it means “loaded and executed”. Chicken-and-the-egg here. onload won’t fire until the execution is complete, so you can’t detect that the load (preload) finished with that event. There’s no preload event, or loaded, or whatever, that tells us only the load was finished.

BUT, IE (from version 4 to 10) gave us a non-standard extension which really was the crux of the “real script preloading” technique. They have supported a script.readyState property which indicates the loading progression, including “loaded” for loading being finished (regardless of execution).

So, you can preload all your scripts, and listen for the readystatechange event to notify you that the script.readyState property has changed, and if it goes to “loaded”, you know the preload is complete, and that script can now be executed, whenever you want it to be.

Sounds complicated

It’s not complicated. It’s actually quite graceful. And super performant and flexible.

More than 2 years ago, I wrote this behavior into LABjs script loader. And it’s been working beautifully and performantly in IE all this time.

Fly in the ointment

IE11 has announced they are removing script.readyState and script.onreadystatechange. This sucks. Because it completely disables and neuters the “real script preloading” technique.

I don’t know know whether IE11 is removing the actual preloading or not, but if you can’t observe the preload completing, then it’s moot, as far as this script loading technique is concerned.

Recovery

Luckily, in LABjs, I also detect and use “ordered async” if present in the browser.

So, the “good news” is, regardless of IE11’s change, LABjs will continue to operate fine, because IE10 added “ordered async”. Phew.

But it really sucks that IE11 will be taking a step backwards (compared to IE4 – IE10!) in terms of this performance and performance-flexibility.

Script Execution Control

2 years ago, Nicholas Zakas and I put forth two proposals for “script execution control”. The goal was to give us a fully standardized way of doing “real script preloading”.

My proposal was to standardize what IE4+ was already doing. My primary argument was “IE4+ is already doing it, so that’s less work for other browsers to come into line with it.” Of course, in light of this revelation, my argument basically falls apart.

Nicholas’ proposal was slightly different, but the same spirit. I could fully support it, too. In fact, LABjs already has a future-thinking feature detect for it!

Either way, the WHATWG needs to act on one of these proposals, or something else, and give us “real script preloading”. I’ve been petitioning for that for 2 years, and have been stonewalled by Ian Hickson.

Plea

Regardless, IE11, please re-consider your decision specifically with relation to script.readyState and script.onreadystatechange.

Please don’t take a step backward in performance and performance-flexibility compared to IE10. Please don’t abdicate your leader-status on script loading capability and performance compared to all other browsers.

If you have to, please help me lead the efforts to finally convince WHATWG to give us something standard, and implement whatever that is, into IE11. Even if it’s not what has already been proposed (or what you already do in IE4 – IE10), whatever it is, if it’s practical, I’ll put it into LABjs so people can take advantage of it.

Please Microsoft. Please IE11. Save “real script preloading”!

This entry was written by getify , posted on Tuesday July 02 2013at 11:07 am , filed under JavaScript, Performance Optimization and tagged , , . Bookmark the permalink . Post a comment below or leave a trackback: Trackback URL.

3 Responses to “IE11: please bring “real script preloading” back”

  • David Storey says:

    It is probably worth filing a bug report in Connect, or talking to someone on the IE team about it, to see what the reasons were. If they still see a use-case for it, they might reconsider. I’m wondering it is one of those things scripts sniff to see if it is IE and give different code.

  • Sameer says:

    Yes please, I’m with you 100% on this! Microsoft/IE Team, you really need to listen for once and leave this be. Remember when instead of simply trying to play catch-up you guys actually innovated with IE and helped improve the web by introducing us to nifty features that eventually got added to the specs since they were so darn good? Push for this to be added too and lots of web devs will thank you for it.

  • Erik says:

    I agree with this article as well!
    It is just plain dump to remove these good features that other browsers are lacking.
    Other browsers should start supporting the readyStates and onload event on scripts/css.
    I believe Opera is the only one who followed IE on this.

Leave a Reply

Consider Registering or Logging in before commenting.

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Notify me of followup comments via e-mail. You can also subscribe without commenting.