1

Locally the app works great, once it is on a server about 50% of the time the jquery libraries aren't loading fast enough and the app throws a bunch of undefined js errors for anything jquery related. I am using backbone.js with jquery, jquery mobile, jquery ui, and required.js. Does the require js file look correct, or is there a way to tell if the scripts have loaded before starting the app?

require.config({

paths: {
    jquery: 'libs/jquery/jquery-1.7.2',
'jquery.ui':'libs/jquery-ui/jquery-ui-1.8.14.custom',
    'jquery.mobile-config': 'libs/jqm/jquery.mobile-config',
    'jquery.mobile': 'libs/jqm/jquery.mobile-1.1.1',
    underscore: 'libs/underscore/underscore-1.3.3',
    backbone: 'libs/backbone/backbone-amd-0.9.2',
text: 'libs/require/text',
    templates: '../templates'
},

shim: {
    'underscore': {
        exports: "_"
    },
    'backbone': {
        deps: ['jquery','underscore'],
        exports: 'Backbone'
    },
    'jquery.ui': {
        deps:['jquery']
    },
    'jquery.mobile-config': {
        deps: ['jquery']
    },
    'jquery.mobile': {
        deps:['jquery','jquery.mobile-config']
    },
    'bundles': {
        deps:['jquery','jquery.mobile','validate','jquery.ui']
    },
},

waitSeconds: 5

});

require([
    'app'
], function(App) {
    $(function() {
        clearInitialLoader();
        App.initialize();
    });
});

3 Answers 3

2

Although I'm not using underscore I also need a ton of plugins to be fetched by requireJS when needed on specific pages. Took a while to get it to work with Jquery Mobile, but this is how my application runs (and I'm not getting any errors any more, so feel free to copy)

1) Add requirejs to page header

<script type="text/javascript" data-main="../js/main" src="../js/libs/require/require.js"></script>

2) I'm using an overrides.js which has this:

// pre-sets
$(document).bind("mobileinit", function(){
$.mobile.autoInitializePage = false;
});

You need this, because jquery mobile will trigger BEFORE require.js (mobileinit vs. docready), which probably is the reason for all your problems = JQM starts running before everything else has loaded and rendered, so you have to trigger JQM manually from your application controller (my app.js)

3) My main.js config

var IS_LOCAL  = /(:\/\/localhost|file:\/\/)/.test(document.location.href);     

requirejs.config({  
         waitSeconds :  (IS_LOCAL? 2 : 45)
      ,  baseUrl:       "../js"
    //,  enforceDefine: true    
      , paths: { 
              app:          'app'
            , overrides:    'overrides'
            , jquery:       'libs/jquery/jquery.min'
            , jqm:          'libs/jquery-mobile/jquery-mobile.min'
            , multiview:    'services/multiview/multiview.min'
            , respond:      'services/respond/respond.min'
            , klass:        'services/klass/klass.min'
            }
      , shim: {
              'overrides':        { deps: ['jquery'] }
            , 'klass':            { deps: ['jquery'] }
            , 'jqm':              { deps: ['jquery'], exports: 'mobile' }
            ,  'services/multiview/multiview.min' :           { deps: ['jquery', 'jqm'] }
            ,  'services/add2home/add2home.min' :             { deps: ['jquery'] }
            ,  'services/datatables/datatables.min' :         { deps: ['jquery'] }
            ... more ... 
            ,  'services/respond/respond.min' :               { deps: ['jquery'] }
                }
        });

    requirejs([ 'overrides', 'jquery', 'jqm', 'multiview', 'respond', 'app'], 
        function( $, overrides, mobile, multiview, respond, App){ 
            App.start();                
            });

4) Then I have an app.js which I runs the application and requires app.js (config files) for every plugin. This way I can load on demand. Looks like this:

define([], function(){
    var start = function() {
        require([ 'overrides', 'jquery', 'jqm','multiview', 'respond' ],function() {

        // your magic goes here...

        // request a plugin:
        $(document).on('pagebeforeshow.add2home', '#login', function() {
            // add2Home - trigger once and lock
            var dom = $('html');
            if ( dom.jqmData('bound') != true ) {
                dom.jqmData('bound', true);
                require(['services/addtohome/app'], function (App) {
                    App.render();
                    });
            };
         });

        // don't forget to trigger JQM manually
        if ( $.mobile.autoInitializePage == false){
            $.mobile.initializePage();
        }
        }); // end require
    } // end start
    return {"start":start};
});

5) This calls the plugin app.js config file, which contains all plugin configuration. Looks like this:

define(['services/addtohome/app', 'services/addtohome/addtohome.min'], function( app, addtohome ) {
function render() {

    if ('standalone' in navigator && !navigator.standalone && (/iphone|ipod|ipad/gi).test(navigator.platform) && (/Safari/i).test(navigator.appVersion)) { 
        var addToHomeConfig = { 
            touchIcon:true,
            animationIn: 'bubble',
            animationOut: 'drop',
            returningVisitor: 'true',
            expire: '10',       
            }; 
        };
    };
return {
    render:render
    };          
});

Of course the more scripts you need the longer it takes, but this setup runs fine pulling in compressed+gzipped 132k of Javascript.

Sign up to request clarification or add additional context in comments.

3 Comments

I was trying your example, does your app test okay on IE8? I keep getting a undefined error for #2. Thanks for the help.
yes, it works. but I needed to modify it a little bit. I will try to post the code tomorrow.
Thanks. I have been searching for this solution for a couple of days. I hadn't twigged to the initializePage configuration.
1

So, in a live site it's pretty much a given you should be stitching and minifying your resources. There are too many resources in an AMD setup to actually try to download them all on-demand in a live site. AMD modules are a development-time convenience, not a deployment solution.

As far as module order, I never had any luck using the exports. The best best, we found, is to wrap the external dependencies in an AMD wrapper. Yes, this means you'll need to re-do it if you update the external library, but it's actually not as big of a deal as you might think.

First you wrap the library

//underscore.js file
define(function(){
  //underscore code
  return underscore
})

Then you can include it anywhere, and get all the benefits of order-guaranteed AMD loading:

//backbone.js (or any other file that wants underscore)
define([underscore],function(_){
  //backbone code
  return Backbone
})

Comments

0

You should take a look at the shim options allowing you to load modules in order.

Also you could use require.js optimizer to concatenate all your files into one.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.