I have the following code using require.js.
utilities.js:
define(["thirdparty-script-A.js"], function(){ ... });
application.js:
define(["utilities", "order!thirdparty-script-A.js", "order!thirdparty-script-B.js"], function(){ ... });
thirdparty-script-B.js has a dependency on thirdparty-script-A.js and will not load properly if thirdparty-script-A.js has not finished loading (executing).
To summarize, the dependency structure looks something like this:
utilities +---> thirdparty-script-A.js <---+ thirdparty-script-B.js
^ ^ ^
| | |
| + |
| |
+------------+ application.js +----------------+
Looking at firebug, I see that the fetch order is:
- utilities
- thirdparty-script-A.js
- application
- thirdparty-script-B.js
And from debugging with console.log() (and from a theoretical standpoint), the load (execution) order is:
- thirdparty-script-A.js
- utilities
- thirdparty-script-B.js
- application
Now here’s the problem.
For the most part, the above works just fine in firefox, chrome, and IE9. However, there is a case where thirdparty-script-B.js fails to load because thirdparty-script-A.js hasn’t finished loading yet. In fact console.logs showed that thirdparty-script-B.js executed FIRST, then third-party-A.js, utilities, and finally application. What is going on? So far, I can only reproduce this problem in IE9.
It is very odd because in application.js, I use the order plugin to guarantee the order in which the two third party scripts load. And yet the scripts execute out of order.
Upon further investigation, I noticed that the problem occurs only when thirdparty-script-A.js takes longer to fetch than thirdparty-script-B.js. Which makes me speculate that the order! plugin doesn’t work with define(). Theoretically, thirdparty-script-B.js should wait on executing even if thirdparty-script-A.js took 20 seconds to fetch and load. That’s how order! behaves, no?
Another theory is that it won’t work if any of the files in order! were required in another module up the chain (thirdparty-script-A.js in utilities.js).
I do have a workaround solution to this. And that is to wrap application.js in a require() and have it load all the traditional scripts first.
require(["order!thirdparty-script-A.js", "order!thirdparty-script-B.js", "application"], function(app){
//app.init
}
For a 60+ script application however, the require list can get long and messy…
Can anyone enlighten my as to why define() and order! behave the way they do?
Thanks a bunch!
And yes, thirdparty-script-A and B are cached. =)
The trick is to wrap everything in modules. I usually do this “repackaging” on third-party plugins that rely on jQuery. That way, you are sure that jQuery is loaded (and
$exists) when the plugin is loaded. In this method, the order plugin is not needed.By “repackaging”, you just wrap the plugin code in a
define()call, with it’s dependencies, and load it normally.in application:
in utilities:
in scriptB
in scriptA
So the order is:
ScriptA could have been loaded and executed earlier since Application depended on it. But to be safe, you should do it this way. That way, you are sure dependencies are loaded properly.