要求为什么以及何时使用shim配置

Requirejs why and when to use shim config

本文关键字:shim 配置 何时使 为什么      更新时间:2023-09-26

我从这里的API中读取了 requires 文档

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

,但我没有得到shim的一部分。为什么我应该使用shim,我应该如何配置,我可以得到一些更多的澄清

谁能举例说明为什么和什么时候我们应该使用垫片?谢谢。

shim的主要用途是不支持AMD的库,但您需要管理它们的依赖关系。例如,在上面的Backbone和Underscore的例子中:你知道Backbone需要下划线,所以假设你这样写你的代码:

require(['underscore', 'backbone']
, function( Underscore, Backbone ) {
    // do something with Backbone
}

RequireJS会同时启动对Underscore和Backbone的异步请求,但是你不知道哪一个会先返回,所以Backbone可能会在加载之前尝试对Underscore做一些事情。

注意:这个下划线/主干示例是在这两个库都支持AMD之前编写的。但是这个原则适用于今天不支持AMD的任何库。

init钩子让你做其他高级的事情,例如,如果一个库通常会导出两个不同的东西到全局命名空间,但你想在一个命名空间下重新定义它们。或者,也许你想在你正在加载的库中的方法上做一些猴子补丁。

更多背景:

  • 升级到RequireJS 2.0给出了order插件在过去如何尝试解决这个问题的一些历史。
  • 请参阅Aaron Hardy的"加载非模块"部分,以获得另一个很好的描述。

根据RequireJS API文档,shim允许您

配置依赖项、导出和自定义初始化旧的、传统的"浏览器全局"脚本没有使用define()声明依赖项并设置模块值。

-配置依赖

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

中指定依赖项。
require(['moduleA','moduleB'],function(A,B ) {
    ...
}

但是由于require本身遵循AMD,所以您不知道哪个会被提前获取。这是shim来拯救的地方。

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

这将确保moduleB总是在moduleA加载之前被获取。

-配置导出

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

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

它将给RequireJS一个对这个模块的本地引用。全局modA仍然存在于页面上。

-自定义初始化旧的"browser global"脚本

这可能是shim配置中最重要的功能,它允许我们将'browser global', 'non-AMD'脚本(也不遵循模块化模式)作为依赖项添加到我们自己的模块中。

让我们假设moduleB是普通的旧javascript,只有两个函数funcA()和funcB()。

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

虽然这两个函数在窗口作用域中都是可用的,RequireJS建议我们通过它们的全局标识符/句柄来使用它们,以避免混淆。因此将shim配置为

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

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

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

希望有帮助。

必须在requires中添加路径。要声明的配置,例如:

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