RequireJS 2.0 dependencies seemingly ignored

Posted on Posted in Uncategorized

After strug­gling for months with Require­JS 2.0 and why it seemed to ignore our depen­den­cies for ordered script load­ing, we final­ly found the issue today and it was a facepalmableteach­able moment.  When set­ting up a mod­ule to use some­thing like Sig­nalR, jQuery must be loaded first.  Search­es quick­ly led to Stack­Over­flow posts that sug­gest­ed con­fig­ur­ing depen­den­cy shims in Require­JS with some­thing like:

require.config({
  shims: {
    'sig­nalr': ['jquery'],
    'back­bone': ['jquery'],
  }
}

In the­o­ry, when lat­er requir­ing 'sig­nalr', Require­JS will see that it needs to load 'jquery' first and all is well:

define(['sig­nalr'], func­tion() { 
  return {
    ini­tial­ize: func­tion() { $.connection.doSomething; }
  };
});

In prac­tice, what we (and many oth­ers, based on the abun­dance of posts) saw was that Sig­nalR com­plained about need­ing jQuery loaded first.  In fact, Devel­op­er Tools showed that not only was the request for jQuery not being pri­or­i­tized before Sig­nalR, but it wasn't being request­ed at all.

Maybe Dependencies Don't Autoload?

A quick check of the Require­JS API con­firms that this should be work­ing.  Some more search­es lead to Stack­Over­flow posts where oth­ers are inex­plic­a­bly hav­ing sim­i­lar prob­lems with depen­den­cies.  My first log­i­cal guess was that Require­JS doesn't auto­mat­i­cal­ly load spec­i­fied depen­den­cies for you, but rather it just orders them cor­rect­ly while still requir­ing you to spec­i­fy every depen­den­cy.  This seemed to defeat the pur­pose of Require­JS, but what the heck.  I tried adding 'jquery' in to our define:

define(['jquery', 'sig­nalr'], func­tion() { 
  return {
    ini­tial­ize: func­tion() { $.connection.doSomething; }
  };
});

This seemed to resolve the issue, though we'd still occa­sion­al­ly see tran­sient "jQuery must be loaded first" errors that went away when­ev­er we tried to debug them.  Even­tu­al­ly, we dis­cov­ered that depen­den­cies were still not work­ing and that Require was not wait­ing for jQuery to fin­ish load­ing before try­ing to load Sig­nalR.   When­ev­er the brows­er cache was cleared and the page reloaded, the same "jQuery must be loaded first" error would appear.  How­ev­er, sub­se­quent refresh­es would fetch the jQuery page from the brows­er cache fast enough that it was fin­ished loaded by the time Require­JS had moved on to Sig­nalR.  At this point, it became obvi­ous that some­thing was fun­da­men­tal­ly wrong with how we were using RequireJS.

Face, meet palm

After look­ing through the Require­JS API more close­ly, it became painful­ly clear why our shims were being ignored.  The Require­JS API con­fig option for depen­den­cies is *shim*, not *shims*.  The extra "s" in our con­fig was caus­ing our depen­den­cy chains to be com­plete­ly ignored.  Search­ing online again, it looks like many of the exam­ples on Stack­Over­flow make the same "shims" typo, thus adding to the con­fu­sion.  Remov­ing the "s" allowed Require­JS to sud­den­ly start work­ing as expected.
require.config({
  shim: {

    'sig­nalr': ['jquery'],
    'back­bone': ['jquery'],

  }
}

Devel­op­er Tools now shows jQuery always being loaded to com­ple­tion before SignalR's is even request­ed.  Our define went back to just con­tain­ing 'sig­nalr', with 'jquery' no longer being nec­es­sary to explic­it­ly spec­i­fy as it is being auto­mat­i­cal­ly pulled in.  Mod­ules sud­den­ly make sense again.
So if you see issues where your Require­JS depen­den­cies don't load as expect­ed, make sure you're not mak­ing the same mis­take we did. Con­fig­ure a shim, not shims.  One lit­tle char­ac­ter makes all the difference.

Leave a Reply

Your email address will not be published. Required fields are marked *