IE11: please bring “real script preloading” back

Published at: 11:07 am - Tuesday July 02 2013

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.

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 functionfine 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.

Script Execution Control

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.

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

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.

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

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.

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.

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.