When I load velocity.ui
, I get an intermittent error on the console:
Velocity UI Pack: Velocity must be loaded first. Aborting.
and none of velocity.ui
's animations are available.
I can reproduce the issue with something as simple as this:
<script>
require.config({
baseUrl: "/static/lib/",
paths: {
jquery: "external/jquery",
velocity: "external/velocity/velocity.min",
"velocity.ui": "external/velocity/velocity.ui.min",
}
});
require(["jquery", "velocity.ui"]);
</script>
When I look at the network requests, I see that velocity
has loaded before velocity.ui
. And velocity.ui
does have define(["velocity"], ...
.
If your project uses jQuery at all, for any reason, then you must make velocity
dependent on the jquery
module. Otherwise, you'll run into the problem you ran into. Create a module called velocity-glue
:
define(['velocity', 'jquery'], function (velocity) {
return velocity;
});
Modify your configuration so that it contains these two entries.
map: {
"*": {
velocity: "velocity-glue",
},
"velocity-glue": {
velocity: "velocity",
},
}
The first entry makes it so that velocity-glue
is used whenever velocity
is required. The second entry makes sure that velocity-glue
can get the original velocity
.
I'm going to use "Velocity" to refer to the product globally: this includes both modules (velocity
and velocity-ui
).
The problem is that Velocity is not a good AMD citizen. By this, I mean that its modules depend on globals and export themselves as globals, even when they are loaded through an AMD loader, which is bad behavior for AMD modules.
Velocity can be used with or without jQuery. When Velocity is used without jQuery, it uses a kind of minimal polyfill that provides only as much of jQuery's functions as Velocity needs. Since Velocity can be used with or without jQuery, its modules not not list jQuery in their dependencies when they call define
, otherwise, they would require you to use jQuery.
Whether or not Velocity is loaded as an AMD module, it installs itself so that it will be accessible as the Velocity
property on one of these if they existr: window.jQuery
window.Zepto
, or window
. Velocity will use the first one that it can use in the order given here. So if neither jQuery nor Zepto are installed, it will be accessible as window.Velocity
. But if jQuery is installed, it will be accessible as window.jQuery.Velocity
. The problem is that both velocity
and velocity.ui
perform the computation choosing between the 3 possible locations independently. Let's consider some scenarios:
Scenario A:
jquery
loads.velocity
installs as window.jQuery.Velocity
.velocity.ui
looks for window.jQuery.Velocity
. Fine.Scenario B:
[jquery
is not loaded yet.]
velocity
installs as window.Velocity
.velocity.ui
looks for window.Velocity
. Fine.(jquery
may or may not load later. It does not matter.)
Scenario C:
velocity
installs itself as window.Velocity
because jQuery is not loaded.jquery
loads.velocity.ui
looks for window.jQuery.Velocity
because window.jQuery
does exist, but window.jQuery.Velocity
does not exist! You get an error.Note that in the scenarios above velocity
will always load before velocity.ui
because velocity.ui
lists velocity
as its dependency. However, the loading order of jQuery relative to the two other modules is not constrained because (as already mentioned) they do not depend on jquery
.
The solution I've given in the first section to this answer fixes the issue by constraining the load order: jquery
will always load before both modules.