Javascript requirejs-执行多个需要的调用

Javascript requirejs-执行多个需要的调用,javascript,performance,requirejs,amd,Javascript,Performance,Requirejs,Amd,我想知道在一个包含多个模块的项目中使用RequireJS的正确方法是什么,关于依赖性较少的多个require调用的性能,与具有所有依赖性的单个require调用的性能相比 让我们举一个例子,对于一个应用程序,我需要加载一些模块:gmap、jquery、module1、module2、module3。一些模块的使用是相当独立的。因此,问题是推荐以下哪种替代方案(假定此代码是加载到页面中的主模块): vs 换句话说,require的性能损失是多少,哪种是最佳实践。这取决于您想要的加载行为 当您需要尚

我想知道在一个包含多个模块的项目中使用RequireJS的正确方法是什么,关于依赖性较少的多个require调用的性能,与具有所有依赖性的单个require调用的性能相比

让我们举一个例子,对于一个应用程序,我需要加载一些模块:
gmap、jquery、module1、module2、module3
。一些模块的使用是相当独立的。因此,问题是推荐以下哪种替代方案(假定此代码是加载到页面中的主模块):

vs

换句话说,
require
的性能损失是多少,哪种是最佳实践。

这取决于您想要的加载行为

当您需要尚未需要的模块时,将发出HTTP请求以加载所需的模块。如果所需模块至少加载了一次,它将存储在require的缓存中,因此当您第二次需要该模块时,它将使用缓存的值

因此,它是一个选择懒惰或急于加载。

需要解决的问题是,每个模块都可以定义它的依赖关系,所以您的第一种方法可能是“最佳实践”。最后,您可能希望使用r.js将应用程序构建到单个js文件中。

我认为第二种方法与requirejs的主要目的相反,requirejs的主要目的是分离不同的程序逻辑。如果您将代码放在一个“模块”中,为什么要使用requirejs。就绩效而言,定义您对绩效的定义很重要。如果是代码执行的速度,那么应该没有明显的差异。加载所有必需的模块后,代码将立即执行。另一方面,如果您所说的性能是:当代码执行开始时,那么显然在第二种方法中,您将由于对所需代码所在的文件的额外请求而产生额外的开销

编辑:


仔细看了这个问题之后,我的答案的第一部分不太合适。代码实际上引用的是外部模块,因此第二个选项并不违背requirejs库的目的,而且实际上是更好的方法,只要组合其依赖项的模块不想做太多的事情。

这里的问题的答案是“它取决于”我是作为一个在大型应用程序中使用过RequireJS,但没有彻底阅读过RequireJS代码的人。(只是指出,了解RequireJS内部和外部的人可能会与我的解释不同。)
require
的成本可以分为三种成本场景:

  • 如果从未加载模块,
    require
    从服务器加载文件,执行文件,执行模块的工厂功能,并返回对模块的引用。(从网络加载文件的成本通常比其他成本低。)

  • 如果模块已加载但从未被要求过,
    require
    执行模块的出厂功能并返回对模块的引用。(这通常发生在优化的应用程序中。)

  • 如果模块已经加载并且是必需的,
    require
    返回对模块的引用

  • 成本情景1>成本情景2>成本情景3

    首先,让我们考虑每个文件有一个模块的情况。应用程序未优化。我有一个名为

    module1
    的模块,这是每个月都需要的。它在主应用程序中的使用可以这样建模:

    define(["module1", <bunch of other required modules>],
        function (module1, <bunch of other modules variables>) {
    
        [...]
    
        if (rare_condition_happening_once_in_a_blue_moon)
            module1.use();
    
        [...]
    });
    
    define([<bunch of required modules>],
        function (<bunch of module variables>) {
    
        [...]
    
        for(iterate a gazillion times)
            require(["module1"], function (module1) {
                module1.use();
            });
    
        [...]
    });
    
    在这种情况下,成本场景1只支付一次,仅此而已。如果我像这样使用
    require

    define(["module1", <bunch of other required modules>],
        function (module1, <bunch of other modules variables>) {
    
        [...]
    
        if (rare_condition_happening_once_in_a_blue_moon)
            module1.use();
    
        [...]
    });
    
    define([<bunch of required modules>],
        function (<bunch of module variables>) {
    
        [...]
    
        for(iterate a gazillion times)
            require(["module1"], function (module1) {
                module1.use();
            });
    
        [...]
    });
    

    在我描述的上下文中,所有“use”函数都需要尽快运行。因此,我并不直接对延迟加载它们感兴趣。在第二种方法中,我认为,例如,如果其中一个模块(例如GMAP)需要更多的加载,那么其他模块可能会更快地执行(henced会更快地向用户显示一些UI操作),不管您使用的是什么方法,在加载所有依赖项之前,您的任何代码都不会运行——因此,如果您预先定义了所有依赖项,这并不重要。我刚刚意识到我的大部分答案都是假的,因为最终在所有依赖项都加载完毕之前,所有代码都不会运行。
    define(["module1", <bunch of other required modules>],
        function (module1, <bunch of other modules variables>) {
    
        [...]
    
        for(iterate a gazillion times)
            module1.use();
    
        [...]
    });
    
    define([<bunch of required modules>],
        function (<bunch of module variables>) {
    
        [...]
    
        for(iterate a gazillion times)
            require(["module1"], function (module1) {
                module1.use();
            });
    
        [...]
    });
    
    define([<bunch of other required modules>],
        function (<bunch of other modules variables>) {
    
        [...]
    
        require(<requirements unknown ahead of time>, function(m1, m2, ...) {
            m1.foo();
            m2.foo();
            [...]
        });
    
        [...]
    });