Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does require.js seem to be loading all my modules on initial page load?

I am developing a single page backbone app using requirejs, and today when I deployed to our beta server, I discovered that the initial page load was around 20 seconds while it fetched all the scripts.

I assumed this was because I was using the dependency array when defining modules like so:

define([
    'ui',
    'models/user',
    'collections/campaigns',
    'collections/groups',
    'collections/keywords',
    'collections/inboxes',
    'collections/templates',
    'collections/contacts',
    'router'
], function (Ui, UserDetails, Campaigns, Groups, Keywords, Inboxes, Templates, Contacts, Router) {

    return {
        start: function () {
            // ...
            // initialize and start app
            // ...
        }
    }
});

Which I believed meant that when the main application module was loaded, every other script would be loaded, due to the fact that every single module was using this method.

I then changed the method of fetching modules to get them as I needed them by calling require('...') directly when I need them like this:

define(function (require) {
    return Backbone.Router(function () {
        // ...
        // route initializtion etc
        // ...

        inbox: function (routeVar) {
            var InboxView = require('InboxView');
            this.inboxView = new InboxView();
            // render view etc
        }
    });
});

However to my surprise, upon running the app again and checking the network tab of chromes developer console - I saw that as before the application is fetching all of my modules, and I am getting the same page load time.

Am I completely missing the point here? As I was under the impression that the scripts would be fetched upon each call of require. Is that not right?

like image 776
jcvandan Avatar asked Aug 06 '12 13:08

jcvandan


1 Answers

In order to asynchronously load AMD modules you must call require and provide a function callback that will be called when the requested module has been loaded:

require(['InboxView'], function(InboxView) {
  // Do something with InboxView here...
});

The sample code you provided called require('InboxView') in a synchronous style. Because you are using the "sugar" syntax, RequireJS will inspect your code, find any synchronous calls to require() and add those dependencies to the top-level dependency list of the module, in effect giving you this:

define(['require', 'InboxView'], function (require) {
  return Backbone.Router(function () {
    // ...
    // route initializtion etc
    // ...

    inbox: function (routeVar) {
        var InboxView = require('InboxView');
        this.inboxView = new InboxView();
        // render view etc
    }
  });
});

...hence why you saw all modules loaded immediately.

Add the async callback to require and you should be fine. Also, if you think about it, how would your code work if RequireJS waited to load the module for InboxView until your route fired without the require call blocking until the load was complete? :)

like image 112
rharper Avatar answered Oct 22 '22 12:10

rharper