Devin Dixon
Devin Dixon

Reputation: 12443

RequireJS Randomly Break

I'm trying to create a site using Jquery Mobile, Backbone and RequireJS. But the problem I am having is the site randomly break and reasons why the break are different:

And I cannot pinpoint our the reason why because it works sometimes but when I refresh it, it suddenly doesn't. I'm loading my code like this(libraries followed by views):

requirejs(["/js/libs/jquery-1.8.3.min", "/js/libs/jquery.mobile-1.2.0.min", "/js/libs/underscore-1.4.3", "/js/libs/json2", "/js/libs/backbone.0.9.9"], function($,JQM, underscore, json2, bb) {

});

requirejs(["/js/views/pageview", '/js/views/home'], function(util) {

    HomeView = new HomeView({el : '#home', 'id' : 'home'})
});

Am I doing something wrong by doing it this way?

Upvotes: 1

Views: 729

Answers (1)

jevakallio
jevakallio

Reputation: 35970

Libraries like jQuery Mobile, Backbone and Underscore are not AMD modules, just plain old javascript files. And because they're not modules, they don't declare dependencies, they just expect to find $ or _ in the global scope.

The loading order of RequireJS is indeterministic - so there's no telling which of them will load first. If Backbone is evaluated first, it won't find the window._ it's looking for and crashes.

RequireJS supports non-AMD modules via the shim config (see docs), which allows you to declare the dependencies between these libraries. After configuring the shim, RequireJS knows how to load the dependent libraries before those that depend on them.

A typical RequireJS config with the shim element would look something like:

requirejs.config({
  //libraries
  paths: {
      jquery:       'libs/jquery/jquery',
      backbone:     'libs/backbone/backbone',
      underscore:   'libs/underscore/underscore',
      jquerymobile: 'libs/jquery.mobile-1.2.0/jquery.mobile-1.2.0',
  },

  //shimming enables loading non-AMD modules
  //define dependencies and an export object
  shim: {
      jquerymobile: {
          deps: ['jquery'],
          exports: 'jQuery.mobile'
      },
      underscore: {
          exports: '_'
      },
      backbone: {
          deps: ['jquerymobile', 'jquery', 'underscore'],
          exports: 'Backbone'
      }
  }
});

The paths part is not mandatory, you could just use the file paths as keys in the shim section. However, when you use the paths aliases, you can then import those libraries with the short name instead of the whole path:

define(['jquery', 'backbone'], function($, Backbone) { ... });

Upvotes: 4

Related Questions