Requirejs为什么以及何时使用填充程序配置


97

我从这里API读取了requirejs文档

requirejs.config({
    shim: {
        'backbone': {
            //These script dependencies should be loaded before loading
            //backbone.js
            deps: ['underscore', 'jquery'],
            //Once loaded, use the global 'Backbone' as the
            //module value.
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                //Using a function allows you to call noConflict for
                //libraries that support it, and do other cleanup.
                //However, plugins for those libraries may still want
                //a global. "this" for the function will be the global
                //object. The dependencies will be passed in as
                //function arguments. If this function returns a value,
                //then that value is used as the module export value
                //instead of the object found via the 'exports' string.
                return this.Foo.noConflict();
            }
        }
    }
});

但我没有得到垫片的一部分。为什么我应该使用垫片以及应该如何配置,我可以进一步澄清一下吗

请任何人举例说明为什么以及何时应使用垫片。谢谢。

Answers:


110

填充程序的主要用途是使用不支持AMD的库,但是您需要管理它们的依赖性。例如,在上面的Backbone and Underscore示例中:您知道Backbone需要Underscore,因此假设您是这样编写代码的:

require(['underscore', 'backbone']
, function( Underscore, Backbone ) {

    // do something with Backbone

}

RequireJS将启动对Underscore和Backbone的异步请求,但是您不知道哪个首先返回,因此Backbone可能会在加载之前尝试对Underscore进行操作。

注意:此下划线/主干示例是在两个库都支持AMD之前编写的。但是,该原则适用于当今不支持AMD的所有库。

“ init”钩子使您可以执行其他高级操作,例如,如果一个库通常会将两个不同的内容导出到全局名称空间中,但是您想在一个名称空间下重新定义它们。或者,也许您想对正在加载的库中的方法进行一些猴子修补。

更多背景:


就像您的示例代码一样,UnderscoreBackbone此处的用法与通常的shim一样,在这种情况下该怎么办?我可以使用require( function() { _.extend({}); })吗?懂_吗?
Stiger

“ RequireJS将启动对Underscore和Backbone的异步请求”->在已经加载库的情况下,是否可以防止这种情况发生?
2015年

1
@Codii对,如果已经加载了库,它将不会启动另一个服务器请求,但是RequireJS的要点是您的代码不需要关心是否/如何发生。也许针对您的特定用例提出了一个新问题?
爆炸

63

根据RequireJS API文档,shim可让您

为不使用define()声明依赖关系和设置模块值的较旧的传统“浏览器全局变量”脚本配置依赖关系,导出和自定义初始化。

-配置依赖

假设您有2个javascript模块(moduleA和moduleB),其中一个(moduleA)依赖于另一个(moduleB)。这两个都是您自己的模块所必需的,因此您可以在require()或define()中指定依赖项

require(['moduleA','moduleB'],function(A,B ) {
    ...
}

但是由于要求自己遵循AMD,所以您不知道哪一个会早拿到。这是垫片拯救的地方。

require.config({
    shim:{
       moduleA:{
         deps:['moduleB']
        } 
    }

})

这将确保在加载模块A之前始终获取模块B。

-配置导出

Shim导出会告诉RequireJS全局对象(当然,假设您在浏览器中,则是窗口)上的哪个成员是实际的模块值。假设moduleA将自身添加window为“ modA”(就像jQuery和下划线分别作为$和_一样),然后我们将导出值设为“ modA”。

require.config({
    shim:{
       moduleA:{
         exports:'modA'
        } 
    }

它将为RequireJS提供对该模块的本地引用。全局modA仍将存在于页面上。

-较旧的“浏览器全局”脚本的自定义初始化

这可能是shim config最重要的功能,它使我们可以在自己的模块中添加“浏览器全局”,“非AMD”脚本(也不遵循模块化模式)作为依赖项。

可以说moduleB是普通的老式javascript,只有两个函数funcA()和funcB()。

function funcA(){
    console.log("this is function A")
}
function funcB(){
    console.log("this is function B")
}

尽管这两个函数在窗口范围内都可用,但RequireJS建议我们通过其全局标识符/句柄使用它们,以免造成混淆。因此将垫片配置为

shim: {
    moduleB: {
        deps: ["jquery"],
        exports: "funcB",
        init: function () {
            return {
                funcA: funcA,
                funcB: funcB
            };
        }
    }
}

来自init函数的返回值用作模块导出值,而不是通过“ exports”字符串找到的对象。这将使我们能够在自己的模块中使用funcB作为

require(["moduleA","moduleB"], function(A, B){
    B.funcB()
})

希望这会有所帮助。


3
容易理解!一个问题:在最后一个示例中,是否仅忽略了“ exports”属性?
Niko Bellic'3

不,它不会被忽略。如果在上一个示例中忽略了“ exports”属性,那么作为参数(在这种情况下为“ B”)传递的对象将是未定义的,因为moduleB不符合AMD的要求,并且不会返回对象供RequireJS使用(因此“ B.funcB”将无法正常工作)。
nalinc

嗯 我以为导出的值将被init函数中返回的对象所覆盖。因此,参数B将是对象{funcA:funcA,funcB:funcB},而不是仅仅是funcB本身。这不是真的吗
Niko Bellic'3

4
Niko Bellic是正确的,出口被忽略了(我刚刚测试过)。对象B是由'init'部分中指定的函数返回的对象。如果删除了“ init”部分,则对象B将成为函数funcB,因此您只需执行B()而不是B.funcB()。显然,在这种情况下funcA将变得不可访问。
user4205580

-2

您必须在requirejs.config中添加路径进行声明,例如:

requirejs.config({
    paths: {
          'underscore' : '.../example/XX.js' // your JavaScript file
          'jquery' : '.../example/jquery.js' // your JavaScript file
    }
    shim: {
        'backbone': {
            deps: ['underscore', 'jquery'],
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                return this.Foo.noConflict();
            }
        }
    }
});

1
此答案是一个代码转储,不解释“为什么以及何时使用shim config”。如果您编辑答案以提供解释,请确保您添加的新内容尚未包含在较早的答案中
路易十六(Louis)

复制粘贴而没有任何积极的反馈
william.eyidi 2016年

填充之前应为逗号:
斯科特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.