为什么require.js似乎在初始页面加载时加载我的所有模块?

时间:2012-08-06 13:51:31

标签: javascript backbone.js requirejs

我正在使用requirejs开发单页骨干应用程序,今天当我部署到我们的beta服务器时,我发现在获取所有脚本时,初始页面加载大约是20秒。

我认为这是因为我在定义模块时使用了依赖关系数组:

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
            // ...
        }
    }
});

我认为这意味着当加载主应用程序模块时,每个其他脚本都会被加载,因为每个模块都使用这种方法。

然后我改变了获取模块的方法,以便在我需要时直接调用require('...')来获取它们:

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

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

然而令我惊讶的是,再次运行应用程序并检查chromes开发人员控制台的网络选项卡 - 我看到之前应用程序正在获取所有模块,并且我得到相同的页面加载时间。

我完全忽略了这一点吗?因为我的印象是每次调用require时都会获取脚本。这不对吗?

1 个答案:

答案 0 :(得分:6)

为了异步加载AMD模块,您必须调用require并提供一个函数回调函数,该函数将在加载请求的模块时调用:

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

您提供的示例代码以同步样式调用require('InboxView')。因为您使用的是“sugar”语法,所以RequireJS将检查您的代码,找到对require()的任何同步调用,并将这些依赖项添加到模块的顶级依赖项列表中,实际上是为了:

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
    }
  });
});

...为什么你看到所有模块立即加载。

将异步回调添加到require,你应该没问题。此外,如果您考虑一下,如果RequireJS等待加载InboxView模块,直到您的路由在没有require调用阻塞的情况下触发,直到加载完成,您的代码将如何工作? :)