Configuring RequireJS to load from multiple CDNs

2019-05-19 00:42发布

I'm using RequireJS on our site and before the files are deployed to production we are using rjs to minify the files. Currently I am creating several minified files, not a single file.

For better load times on our site we are also using multiple CDNs so the browser will open more download streams and the static content will load as fast as possible.

Here lies my problem. I can configure RequireJS through the baseUrl parameter to load my scripts from our CDN, but is there a way to configure RequireJS to use a random baseUrl? I know by default this isn't possible, but I was hoping maybe someone here can help me by suggesting a plugin or a method that will do the trick.

The only solution I found was to define the path manually to each file, giving them different CDNs on each definition, but I really hope that there's a better way to do it. An automatic way and not a manual one.

If there's anything I can add, show or answer please let me know.

Thanks in advance.

1条回答
闹够了就滚
2楼-- · 2019-05-19 01:22

I don't think the official API supports what you want, but here are some ideas for workaround:

Option 1: embed expressions into the paths config section that randomizes which CDN is used. Below is an example for jQuery but you could repeat something similar for different libraries:

<script src="js/lib/require.js"></script>
<script>
var jqCDNs = [ 'http://code.jquery.com/jquery-2.0.2', 'http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.2' ]

require.config({
    paths: {
        foomodule: 'libs/foo',
        // create array with two elements: a random CDN url plus a local fallback version
        jquery:  [ jqCDNs[Math.floor(Math.random() * jqCDNs.length)], 'jquery-2.0.2' ]
    }
});

require( ['jquery'], function(jq) {
    // do stuff
});

Option 2: Override RequireJS's load method as described in Fine-grained URL control:

<script src="require.js"></script>
<script>

require.config({
    paths: {
        foomodule: 'libs/foo',
        jquery:  [ '{CDN_PREFIX}/jquery-2.0.2' ]
    }
});

(function () {
  var CDNs = [ 'http://code.jquery.com/', 'http://ajax.aspnetcdn.com/ajax/jQuery/' ]
  var load = requirejs.load;
  requirejs.load = function (context, moduleId, url) {
    var prefix = CDNs[Math.floor(Math.random() * CDNs.length)];
    //modify url here, then call original load
    url = url.replace('./{CDN_PREFIX}', prefix);
    return load(context, moduleId, url);
  };

  require( ['jquery'], function(jq) {
      // do stuff
  });

}());

</script>

Option 3: Write your own Loader Plugin. The below sample code is not a complete solution but it shows the idea of what I mean:

// normal RequireJS config stuff
require.config({
    paths: {
        foomodule: 'libs/foo',
        jquery:  [ 'http://code.jquery.com/jquery-2.0.2', 'http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.2' ]
    }
});

// crud loader plug-in. See http://requirejs.org/docs/plugins.html for more things to think about
//
// RequireJS supports an array of path values but it always takes them in order
// this loader plug-in is a hack to shuffle the order before RequireJS does its request
define('cdn', function() {

    //credit: http://stackoverflow.com/a/12646864/151212
    function shuffleArray(array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }    

    return {
        load: function (name, req, onload, config) {
            // if the module has an array of path configs,
            if (config.paths && config.paths[name] && config.paths[name].length && config.paths[name].length > 1) {
                // shuffle the order of it
                shuffleArray(config.paths[name])
            }
            // and then pass on to the normal RequireJS process
            req([name], function (value) {
                onload(value);
            });
        }
    };
});

// then use the randPath! prefix before any module that you want to use this shuffle process
require( ['cdn!jquery'], function(jq) {
    // do stuff
});
查看更多
登录 后发表回答