RequireJS-该“文件”的目的是什么;“出口”;垫片的性能

RequireJS-该“文件”的目的是什么;“出口”;垫片的性能,requirejs,Requirejs,以下垫片中“导出”属性的用途是什么?真的需要吗 requirejs.config({ shim: { 'backbone': { deps: ['underscore', 'jquery'], exports: 'Backbone' } } }); 我这样问是因为它看起来是多余的-当模块包含在依赖项列表中时,我们将再次指定导出的名称作为函数参数: define(['backbone'], funct

以下垫片中“导出”属性的用途是什么?真的需要吗

requirejs.config({
    shim: {
        'backbone': {
            deps: ['underscore', 'jquery'],
            exports: 'Backbone'
        }
    }
});
我这样问是因为它看起来是多余的-当模块包含在依赖项列表中时,我们将再次指定导出的名称作为函数参数:

define(['backbone'], function (Backbone) {
  return Backbone.Model.extend({});
});

Shim exports是为了让requirejs知道如何处理非AMD模块。如果没有它,在模块启动时,define块中的依赖项仍将被加载。它向requirejs发出信号,表示它已停止加载资源,并且模块可以开始使用它


至少,我是这么看的。

如果您的示例中没有使用
shim
,那么作为参数传入的
Backbone
对象将是未定义的,因为Backbone不符合AMD,并且不会返回一个对象供RequireJS使用

define(['backbone'], function (Backbone) {
  // No shim? Then Backbone here is undefined as it may
  // load out of order and you'll get an error when
  // trying to use Model
  return Backbone.Model.extend({});
});
为了提供一点上下文,我将使用r.js Optimizer吐出的代码,但在本例中我将对其进行简化。通过阅读乐观主义者的作品,它帮助我理解了它的意义

加垫片的主干有点像这样:

// Create self invoked function with the global 'this'
// passed in. Here it would be window
define("backbone", (function (global) {
    // When user requires the 'backbone' module
    // as a dependency, simply return them window.Backbone
    // so that properites can be accessed
    return function () {
        return global.Backbone;
    };
}(this)));
关键是当您请求一个模块时,给RequireJS一些返回给您的东西,它将确保在这样做之前先加载该模块。在Optimizer的情况下,它只需在手之前嵌入库。

如果您不使用“导出”主干,则无法在模块到主干(window.Backbone)中获取区域设置引用,该引用在Backbone.js中定义

//without export Backbone
shim : {
  'bbn':{
        //exports:'Backbone',
        deps:['underscore']
    },
    'underscore': {
        exports: '_'
    }
};


require(['bbn'], function(localBackbone) {
  //localBackbone undefined.
  console.log('localBackbone:,' localBackbone);
});
RequireJs解释如下:

//RequireJS will use the shim config to properly load 'backbone' and give a local
//reference to this module. The global Backbone will still exist on
//the page too.
define(['backbone'], function (Backbone) {
  return Backbone.Model.extend({});
});
RequireJS将使用shim配置来获取全局主干

function getGlobal(value) {
        if (!value) {
            return value;
        }
        var g = global;
        each(value.split('.'), function (part) {
            g = g[part];
        });
        return g;
    }

还请注意,您可能希望在“导出”中使用插件的实际导出。比如说,

requirejs.config({
    shim: {
        'jquery.colorize': {
            deps: ['jquery'],
            exports: 'jQuery.fn.colorize'
        },
        'jquery.scroll': {
            deps: ['jquery'],
            exports: 'jQuery.fn.scroll'
        },
        'backbone.layoutmanager': {
            deps: ['backbone']
            exports: 'Backbone.LayoutManager'
        },
        "jqueryui": {
            deps: ["jquery"],
            //This is because jQueryUI plugin exports many things, we would just 
            //have reference to main jQuery object. RequireJS will make sure to
            //have loaded jqueryui script.
            exports: "jQuery"  
        },
        "jstree": {
            deps: ["jquery", "jqueryui", "jquery.hotkeys", "jquery.cookie"],
            exports: "jQuery.fn.jstree"
        },
        "jquery.hotkeys": {
            deps: ["jquery"],
            exports: "jQuery"  //This plugins don't export object in jQuery.fn
        },
        "jquery.cookie": {
            deps: ["jquery"],
            exports: "jQuery" //This plugins don't export object in jQuery.fn
        }
    }
});

更多信息:

谢谢西蒙。我不是问为什么使用垫片,而是问为什么垫片内部需要“导出”属性?然而,您的回答给了我一个线索,即“导出”用于识别非AMD模块引入的全局。现在我又读了一遍文档,它们说:“一旦加载,使用全局‘主干’作为模块值”。使用“主干”作为函数参数只会给这个模块提供一个本地引用。再加上一点,有时对全局进行本地引用是非常重要的,例如,在一个页面上,可以加载同一个库的多个版本。例如,如果您正在编写一个依赖于特定版本的Knockout的插件,您可能不想使用全局
ko
变量,而只想使用传递到回调中的本地变量。至少Backbone.js 1.3.3是AMD Compliant接受的答案甚至不回答问题@伊恩·江的答案更好!