最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Wrapper to allow a module to work with AMDCommonJs or script tags? - Stack Overflow

programmeradmin3浏览0评论

I just took a shot at wrapping one of our modules that is meant to be included via a <script> tag in some boilerplate to allow optional AMD loading with requirejs.

It was quite painful and the best I could e up with is:

(function(){
var exports, jQuery;
if (typeof window.define === 'function' && typeof window.requirejs === 'function') {
    exports     = {};
    define(['jquery'], function (jq) {
        jQuery = jq;
        return thisModule();
    });
} else {
    exports     = window;
    jQuery      = window.jQuery;
    thisModule();
}


function thisModule() {
}

})();

Notice that this is

  • A LOT of boilerplate
  • Requires you to declare dependencies in variables (only jQuery in this case thankfully) AND amd
  • Needs yet more code if I want to have CommonJs support.

I am primarily concerned about the second point as that one is going to be a doozy when I get beyond wrapping our core files. I'm sure there's some neat(er) wrapper implementations out there but I can't find any.

Anyone have any tips?

I just took a shot at wrapping one of our modules that is meant to be included via a <script> tag in some boilerplate to allow optional AMD loading with requirejs.

It was quite painful and the best I could e up with is:

(function(){
var exports, jQuery;
if (typeof window.define === 'function' && typeof window.requirejs === 'function') {
    exports     = {};
    define(['jquery'], function (jq) {
        jQuery = jq;
        return thisModule();
    });
} else {
    exports     = window;
    jQuery      = window.jQuery;
    thisModule();
}


function thisModule() {
}

})();

Notice that this is

  • A LOT of boilerplate
  • Requires you to declare dependencies in variables (only jQuery in this case thankfully) AND amd
  • Needs yet more code if I want to have CommonJs support.

I am primarily concerned about the second point as that one is going to be a doozy when I get beyond wrapping our core files. I'm sure there's some neat(er) wrapper implementations out there but I can't find any.

Anyone have any tips?

Share Improve this question edited Feb 6, 2013 at 19:47 George Mauer asked Feb 6, 2013 at 18:58 George MauerGeorge Mauer 122k139 gold badges396 silver badges630 bronze badges 4
  • 1 One thought: I wouldn't test typeof window.requirejs == 'function'. You probably don't care about the AMD implementation. Instead test window.define.amd. But that's just a tweak. – Scott Sauyet Commented Feb 13, 2013 at 14:43
  • Thanks @ScottSauyet - I think I saw that somewhere in the knockout.js source and was wondering if that's a better way. – George Mauer Commented Feb 13, 2013 at 15:41
  • Note also that Require has an option to load non-AMD modules reasonably well with only a small amount of configuration. So although yours might be an interesting goal, you might be able to get away without it. – Scott Sauyet Commented Feb 13, 2013 at 16:25
  • @ScottSauyet - yup, I'm aware of the shim - mine is also partially an exercise in getting our devs to declare their dependencies explicitly. – George Mauer Commented Feb 13, 2013 at 16:50
Add a ment  | 

3 Answers 3

Reset to default 8

What you are trying to re-create something that already exists, I did exactly the same thing, ing up with a slightly different solution in my StackOverflow question.

To cut a long story short the name you need to know is "Universal Module Definition" and there's a GitHub located at https://github./umdjs/umd with a variety of different implementations.

Are you trying to do this for an internal module, or an external module?

If you're not require-ing in additional modules, would it be possible to build your modules assuming AMD, and then just shim out the define() function somewhere else in your code, if it's not there? Of course, you'll have to use named modules, but you'd have to basically do that anyway...

If your modules all return their exports from the define() function, it would be relatively simple, and your shimmed define function could look something like this:

//Whatever additional guards you want could be added, of course...
if (typeof(window.define) === undefined){
  window.define = function(name, deps, callback){
    window.myNamespace[name] = callback();
  };
}

At least that way you wouldn't have to add the boilerplate to every module...

If you've got a larger library with lots of interdependent sub-modules, you're probably just going to have to mit to using Require all the way, or not, and then use your wrapper code around your whole library to handle AMD support, the way Jquery and Knockout JS do it.

After hacking on this I managed to e up with the following which seems significantly better and could even be included as a shim in a regular script tag:

A couple notes and drawbacks.

  • You have to replace any explicit setting on the window object with the exports object
  • It assumes that any dependency exists as a similarly named property on the window object (though it also makes sure to place that property there). This is generally safe enough in my case but you could easily hack in something like the requirejs paths configuration.
  • Actually I'm not convinced that the entire exports concept is particularly necessary, or at least not necessary in all cases.
(function () {
    var define, exports = {};
    if (window.define && window.define.amd) {
        define = window.define;
    } else {
        exports = window;
        define = function (name, dependencies, fn) {
            var deps = [];
            for (var i = 0; i < dependencies.length; i++)
                deps.push(window[dependencies[i]]);
            var module = fn.apply(undefined, deps);
            if (!window[name]) window[name] = module;
        };
    }

    define('mylib.interaction', ['jQuery', 'mylib.core', 'jQuery.UI'], function($, mylib) {
        return /*....blah...*/;
    })
})()
发布评论

评论列表(0)

  1. 暂无评论