Requirejs why and when to use shim config

后端 未结 3 2032
故里飘歌
故里飘歌 2020-11-28 18:47

I read the requirejs document from here API

requirejs.config({
    shim: {
        \'backbone\': {
            //These script dependencies s         


        
相关标签:
3条回答
  • 2020-11-28 19:27

    You must add paths in requirejs.config to declare, example:

    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();
                }
            }
        }
    });
    
    0 讨论(0)
  • 2020-11-28 19:40

    As per RequireJS API documentation, shim lets you

    Configure the dependencies, exports, and custom initialization for older, traditional "browser globals" scripts that do not use define() to declare the dependencies and set a module value.

    - Configuring dependencies

    Lets say you have 2 javascript modules(moduleA and moduleB) and one of them(moduleA) depends on the other(moduleB). Both of these are necessary for your own module so you specify the dependencies in require() or define()

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

    But since require itself follow AMD, you have no idea which one would be fetched early. This is where shim comes to rescue.

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

    This would make sure moduleB is always fetched before moduleA is loaded.

    - Configuring exports

    Shim export tells RequireJS what member on the global object (the window, assuming you're in a browser, of course) is the actual module value. Lets say moduleA adds itself to the window as 'modA'(just like jQuery and underscore does as $ and _ respectively), then we make our exports value 'modA'.

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

    It will give RequireJS a local reference to this module. The global modA will still exist on the page too.

    -Custom initialization for older "browser global" scripts

    This is probably the most important feature of shim config which allow us to add 'browser global', 'non-AMD' scripts(that do not follow modular pattern either) as dependencies in our own module.

    Lets say moduleB is plain old javascript with just two functions funcA() and funcB().

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

    Though both of these functions are available in window scope, RequireJS recommends us to use them through their global identifier/handle to avoid confusions. So configuring the shim as

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

    The return value from init function is used as the module export value instead of the object found via the 'exports' string. This will allow us to use funcB in our own module as

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

    Hope this helped.

    0 讨论(0)
  • 2020-11-28 19:45

    A primary use of shim is with libraries that don't support AMD, but you need to manage their dependencies. For example, in the Backbone and Underscore example above: you know that Backbone requires Underscore, so suppose you wrote your code like this:

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

    RequireJS will kick off asynchronous requests for both Underscore and Backbone, but you don't know which one will come back first so it's possible that Backbone would try to do something with Underscore before it's loaded.

    NOTE: this underscore/backbone example was written before both those libraries supported AMD. But the principle holds true for any libraries today that don't support AMD.

    The "init" hook lets you do other advanced things, e.g. if a library would normally export two different things into the global namespace but you want to redefine them under a single namespace. Or, maybe you want to do some monkey patching on a methods in the library that you're loading.

    More background:

    • Upgrading to RequireJS 2.0 gives some history on how the order plugin tried to solve this in the past.
    • See the "Loading Non-Modules" section of This article by Aaron Hardy for another good description.
    0 讨论(0)
提交回复
热议问题