包装器允许模块使用AMD / CommonJs或脚本标签?

时间:2013-02-06 18:58:35

标签: javascript amd boilerplate commonjs dynamic-script-loading

我刚刚开始包装我们的一个模块,这些模块通过某个样板中的<script>标签包含在内,以允许使用requirejs加载可选的AMD。

这是非常痛苦的,我能想到的最好的是:

(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() {
}

})();

请注意,这是

  • 很多样板
  • 要求你在变量中声明依赖项(在这种情况下,谢天谢地只有jQuery)和amd
  • 如果我想获得CommonJs支持,则需要更多代码。

我主要关心的是第二点,因为当我超越包装我们的核心文件时,这将是一个愚蠢的。我确定那里有一些整洁的(呃)包装器实现,但我找不到任何。

任何人都有任何提示吗?

3 个答案:

答案 0 :(得分:8)

你正在尝试重新创建已存在的东西,我做了完全相同的事情,在my StackOverflow question中提出了略有不同的解决方案。

简而言之,你需要知道的名称是“通用模块定义”,而且https://github.com/umdjs/umd有一个GitHub,有各种不同的实现。

答案 1 :(得分:0)

您是否尝试为内部模块或外部模块执行此操作?

如果你不需要额外的模块,是否可以构建你的模块,假设是AMD,然后只是在代码中的其他地方重新调出define()函数,如果它不存在?当然,你必须使用命名模块,但无论如何你必须基本上这样做......

如果你的模块都从define()函数返回它们的导出,那么它会相对简单,你的shimmed define函数看起来像这样:

//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();
  };
}

至少这样你就不必将样板添加到每个模块......

如果你有一个包含许多相互依赖的子模块的更大的库,你可能只需要提交使用Require或不使用,然后在整个库周围使用你的包装代码处理AMD支持,就像Jquery和Knockout JS那样。

答案 2 :(得分:0)

在对此进行攻击之后,我设法提出以下内容,这些内容看起来要好得多,甚至可以作为常规脚本标签中的垫片包含在内:

一些注意事项和缺点。

  • 您必须使用导出对象
  • 替换窗口对象上的任何显式设置
  • 它假定任何依赖项作为窗口对象上类似命名的属性存在(尽管它也确保将该属性放在那里)。在我的情况下,这通常足够安全,但你可以很容易地破解像requirejs路径配置这样的东西。
  • 实际上我并不相信整个出口概念是特别必要的,或者至少在所有情况下都没有必要。
(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...*/;
    })
})()