可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
What is the purpose of the "exports" property in the shim below? Is it really required?
requirejs.config({
shim: {
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
}
});
I ask because it seems redundant - when the module is included in a dependency list, we will specify the exported name again as the function argument:
define(['backbone'], function (Backbone) {
return Backbone.Model.extend({});
});
回答1:
If shim
is not used in your example then the Backbone
object you pass in as a parameter would be undefined as Backbone is not AMD compliant and does not return an object for RequireJS to use.
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({});
});
To give a bit of context I will use the code that the r.js optimiser spits out but I will simplify it for this example. It helped me understand the point of it by reading what the optimiser produces.
The shimmed Backbone would be a little like this:
// 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)));
The point is to give RequireJS something to return back to you when you ask for a module, and it will ensure that is loaded first before doing so. In the case of the optimiser, it will simply embed the library before hand.
回答2:
If you don't use "export" Backbone, then you can't get the locale reference in module to Backbone(window.Backbone) which is defined in backbone.js.
//without export Backbone
shim : {
'bbn':{
//exports:'Backbone',
deps:['underscore']
},
'underscore': {
exports: '_'
}
};
require(['bbn'], function(localBackbone) {
//localBackbone undefined.
console.log('localBackbone:,' localBackbone);
});
RequireJs explains as follow:
//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 will use shim config to get global Backbone
function getGlobal(value) {
if (!value) {
return value;
}
var g = global;
each(value.split('.'), function (part) {
g = g[part];
});
return g;
}
回答3:
Also note that you might want to use actual export of the plugin in "exports". For example,
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
}
}
});
More: https://github.com/jrburke/requirejs/wiki/Upgrading-to-RequireJS-2.0#wiki-shim
回答4:
Shim exports is for letting requirejs know how to handle non-AMD modules. Without it, dependencies in the define block will still be loading, while the module starts. It signals requirejs that it has stopped loading the resource and that modules can start using it.
At least, that's how i see it.