FF4, script loaders, and order preservation

This has certainly been an eventful day so far. I woke up this morning to this ominous tweet from @3rdEden. I thought surely I was reading that wrong, but I scrambled to try and install a copy of FF4 nightly (aka “minefield”) to try and confirm. Sadly, a few minutes later, I confirmed that it was in fact true: FF was no longer preserving execution order (as insertion order) on dynamically injected <script> nodes.

Then I thought to myself: surely this is just a regression bug… FF has always preserved execution order on <script> tags (hint: so has Opera). Also, the recent support for “async” and “defer” properties was specifically designed around unpinning scripts from execution order and onload dependency blocking, so the natural assumption is that the desired and correct behavior for a “naked” <script> tag without such attributes would be to continue as it always has in FF: insertion-order execution.

So I figured I’d just file a bug with Mozilla and surely they’d just fix that little hiccup. Then the bombshell… I found the bug report that changes everything. In short, Mozilla intentionally removed support for preserving insertion-order execution of inserted scripts. Not an accidental regression bug in a nightly release, but a landmark and fundamental feature change they’ve made to the browser. And no, they didn’t engage anyone like me (or others that are highly invested in this area) in any discussions ahead of time to examine the impact such a change might have — they just made the change. Bam.

Why do we care?

Let’s back up. Why do we care that Mozilla is changing this behavior with the upcoming FF4? The reason I care, and you should too, is because it severely cripples script loaders (like LABjs). If you’re not aware, the affected script loading tricks/tactics are in several different loaders (including the “Order” plugin for RequireJS), and LABjs is in use on a number of high profile sites, including the New Twitter, Zappos, and Vimeo.

Before I go any further, let me explain exactly under what circumstances and how this change by Mozilla is going to change things for the script loader landscape, especially for LABjs.

The specific use case that is affected is: dynamic script loading of multiple scripts (one or more of which are from remote domains) which have execution order dependencies so their order must be preserved.

If you are only loading local scripts, or if you are loading scripts in parallel and you don’t care at all about their execution order (they are unrelated entirely), or if you are only loading one script, then you are probably not affected. So move along. Well, unless you use another site that does, and that site will now fail in FF4. Then I guess you should care. :)

Why is this relevant to LABjs?

So, let me try to explain very simple boiled down why LABjs relied on the previous behavior in FF, and thus what the effect will now be in FF4 going forward.

LABjs’ main goal is to allow you to load any script, from any location (local or remote), in parallel (for better performance), but maintain/enforce execution order if you need to because of dependencies. What does this mean? It means that LABjs needs to be able to download all scripts in parallel, but be in control of when/how those scripts execute. Because one of the later scripts might download quicker than the earlier scripts… but we need the later script to “wait” for the earlier script to finish downloading and run.

When you use <script> tags in your HTML, you already get this correct behavior by default. But LABjs is designed to replace those <script> tags with $LAB API calls that load the scripts dynamically and in parallel, which achieves (in some cases, much) better performance than just <script> tags alone.

Page 1 of 3 | Next page