我正在使用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时都将获取脚本。那不对吗?
最佳答案
为了异步加载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
调用没有阻塞,直到加载完成,您的代码将如何工作? :)