Just to clear up any confusion around exports , he suggested that any shim library would attach a property to the global context ( window or root ) or modify an existing global property (like the jQuery plugin). When requireJS receives a command to load the dependent dependency, it parses the global context for the property corresponding to the exports value of this shim configuration, and if it finds it, returns it as the value of this module. If it does not find it, it loads the associated script, waits for its execution, then finds the global character and returns it.
It is important to remember that if the shim configuration does not contain the value exports , any init method in this config will NOT be executed. The dependency loader must find the value for the module (this is what exports says) before this module can be initialized, so a property is required if there is an init strip for this module.
: I also need to indicate that if the module in question calls define anywhere, any shim configuration you have for this module will be ignored. This actually caused me some headaches because I wanted to use the shim configuration to call the jQuery jQuery.noConflict(true) method for un-globify jQuery and keep it in the scope only for modules that require it, but couldn't force its work. (See the Update below for information on how to easily do this using a map configuration instead of a shim configuration.)
update 2: a recent question about google group requireJS made me realize that my explanation might be a little misleading, so I would like to clarify. A JS request will reuse the encrypted dependency if it has been downloaded via requireJS at least once. That is, if you just use the <script> on the hosting page (e.g. underline), for example:
<script src='lib/underscore.js'></script> <script src='lib/require.js' data-main='main.js'></script>
... and you have something similar in your requireJS configuration:
paths: { 'underscore': 'lib/underscore' }, shim: { 'underscore': { exports: '_' } }
Then the first time you execute define(['underscore'], function (_) {}); or var _ = require('underscore'); RequireJS will reload the underscore library, rather than reuse the previously defined window._ , because as far as requireJS knows, you never loaded the underscore before. Of course, he can check if _ defined in the root area, but he has no way to check that _ already has the one specified in the paths configuration. For example, both prototype and jquery are assigned window.$ By default, and if requireJS assumes that "window. $" Is jQuery, when it is actually a prototype, you will end up in poor condition.
All this means that if you mix and match script loading styles, for example, your page will end up like this:
<script src='lib/underscore.js'></script> <script src='lib/require.js' data-main='main.js'></script> <script src='lib/underscore.js'></script>
Where the second instance of the underscore is the one loaded by requireJS.
Basically, a library should be loaded via requireJS so that requireJS knows about it. However, the next time you need to emphasize, requireJS will go "hey, I already loaded this, so just cancel all exports and don't worry about loading another script."
This means that you have two real options. One of them is what I consider an anti-pattern: just don't use requireJS to express dependencies for global scripts. That is, as long as the library attaches the global root context, you can access it if this dependency is not explicitly required. You can understand why this is an anti-pattern - you basically just excluded most of the benefits of using the AMD loader (explicit dependency list and portability).
Another, better option is to use requireJS to load everything, to the extent that the only actual script tag you have to create yourself is the one that originally requires requireJS. You can use gaskets, but in 95% of cases it is really not that difficult to add an AMD wrapper to the script. It may take a little more work to convert all your non-AMD libraries into AMD-compatible, but once you have done one or two, it becomes much easier - I can use any common jQuery plugin and convert it to an AMD module in less than a minute. Usually it's just a matter of adding
define(['jquery'], function (jQuery) {
above and
return jQuery; });
at the bottom. The reason I have jquery matching with jquery rather than $ is because I noticed that most plugins these days are wrapped in closures like this:
(function ($) {
And it is a good idea to pay attention to the estimated volume. You can, of course, match 'jquery' with $ directly, assuming the plugin does not expect to find jquery instead of $ . This is just the basic shell of AMD - the more complex ones, as a rule, try to determine what type of bootloader is used (commonJS vs AMD vs regular ol globals) and use a different boot method depending on the result. You can easily find examples of this with a few seconds on Google.
Update. The workaround I used to support using jQuery.noConflict(true) with RequireJS worked, but there was a very small modification to the jQuery source for it, and since then I realized that it is a much better way to do the same thing without changing jQuery. Fortunately, James Burke, the author of RequireJS, added it to the RequireJS documentation: http://requirejs.org/docs/jquery.html#noconflictmap