支持CommonJS和AMD

时间:2012-12-02 20:10:46

标签: javascript amd commonjs

有没有办法创建一个支持以下所有模块格式的javascript微库(没有依赖的库):

  • 异步模块定义
  • CommonJS的
  • 将库的导出公开为全局名称空间对象(无加载程序)

6 个答案:

答案 0 :(得分:49)

是的,我应该回答ded及其令人敬畏的模块:

(function(name, definition) {
    if (typeof module != 'undefined') module.exports = definition();
    else if (typeof define == 'function' && typeof define.amd == 'object') define(definition);
    else this[name] = definition();
}('mod', function() {
    //This is the code you would normally have inside define() or add to module.exports
    return {
        sayHi: function(name) {
            console.log('Hi ' + name + '!');
        }
    };
}));

然后可以使用:

    AMD中的
  1. (例如使用requireJS):

    requirejs(['mod'], function(mod) {
        mod.sayHi('Marc');
    });
    
  2. commonJS中的
  3. (例如nodeJS):

    var mod = require('./mod');
    mod.sayHi('Marc');
    
  4. 全局
  5. (例如在HTML中):

    <script src="mod.js"></script>
    <script>mod.sayHi('Marc');</script>
    
  6. 这种方法需要得到更多的宣传 - 如果jQuery和co。开始使用它会更容易生活!

答案 1 :(得分:22)

这是a list of various cross-compatible module formats

我怀疑你正在寻找的是他们所谓的“commonjsStrict.js

答案 2 :(得分:7)

uRequire,通用模块&amp;资源转换器就是这样做的工具。

  • 主要是将AMD和CommonJS 转换为 UMD / AMD / CommonJS / Plain脚本(不需要AMD加载程序)

  • 它允许声明性地导出模块,其中包含noConflict()

  • 它可以在构建模块时操作模块(注入/替换/删除依赖项或代码)。

  • 它转换为coffeescript,coco,Livescript,icedCoffeescript,你可以在一个衬里添加你自己的转换!

答案 3 :(得分:1)

关于@marc的这个答案稍微更新一下我也赞成ded并且稍微更新了它以获得最新的更新:

(function (name, definition, context, dependencies) {
  if (typeof context['module'] !== 'undefined' && context['module']['exports']) { if (dependencies && context['require']) { for (var i = 0; i < dependencies.length; i++) context[dependencies[i]] = context['require'](dependencies[i]); } context['module']['exports'] = definition.apply(context); }
  else if (typeof context['define'] !== 'undefined' && context['define'] === 'function' && context['define']['amd']) { define(name, (dependencies || []), definition); }
  else { context[name] = definition(); }
})('events', function () {
  // Insert code here
  return {
    sayHi: function(name) {
      console.log('Hi ' + name + '!');
    }
  };
}, (this || {}));

最后的对象是对父作用域或当前作用域的引用,假设你有一个正在编写的包,这只是一块饼,那个上下文可能是一个名称间隔的对象,这个只是一块馅饼。

此外,如果您希望拥有依赖项,则在支持数组的作用域之后的末尾有一个可选参数,在这种情况下,definition参数可以将每个依赖项用作参数。此外,为方便起见,在node-js平台内部将需要数组中列出的依赖项。

请参阅:https://gist.github.com/Nijikokun/5192472以获取真实示例。

答案 4 :(得分:0)

我已经解决了这个问题,并设法轻松支持:

  • Dojo AMD(参考RequireJS规范)
  • jQuery(在$ / jQuery.fn。[your_library_here]下)
  • node.js使用vanilla require('path_to.js')
  • 浏览器窗口。[your_library_here]

它使用依赖注入和IIFE的组合来完成工作。

见下文:

/*global jQuery:false, window:false */
// # A method of loading a basic library in AMD, Node.JS require(), jQuery and Javascript's plain old window namespace.
(function(exporterFunction) {
exporterFunction('cll',
    function(a,b) {
        return a+b;
    }
);
})(
    (function() { // Gets an exportFunction to normalize Node / Dojo / jQuery / window.*

        if ((typeof module != 'undefined') && (module.exports)) { // Node Module
            return function(library_name,what_was_exported) {
                module.exports = what_was_exported;
                return;
            };
        }
        if (typeof define != 'undefined' && define.hasOwnProperty('amd') && define.amd) { // Dojo AMD
            return function(library_name,what_was_exported) {
                define(function() {
                    return what_was_exported;
                });
            };
        }
        if (typeof jQuery === 'function') { // jQuery Plugin
            return function(library_name,source) {
                jQuery.fn[library_name] = source;
                return;
            };
        }
        if (typeof window != 'undefined') { // Fall down to attaching to window...
            return function(library_name,what_was_exported) {
                window[library_name] = what_was_exported;
            };
        }

    })(),
    (function() { 
        // ## Other Parameters Here
        // You could add parameters to the wrapping function, to include extra 
        // functionalilty which is dependant upon the environment... See 
        // https://github.com/forbesmyester/me_map_reduce for ideas.
        return 'this_could_be_more_arguments_to_the_main_function'; 
    })()
);

公共要点https://gist.github.com/forbesmyester/5293746

答案 5 :(得分:0)

这是基于Nijikokun的回答。由于RequireJS不鼓励使用显式模块名称,因此在此版本中已省略。加载器的第二个参数描述了依赖关系。如果您不需要加载任何内容,请通过[]

var loader = function(name, dependencies, definition) {
  if (typeof module === 'object' && module && module.exports) {
      dependencies = dependencies.map(require);
      module.exports = definition.apply(context, dependencies);
  } else if (typeof require === 'function') {
    define(dependencies, definition);
  } else {
    window[name] = definition();
  }
};

loader('app', ['jquery', 'moment'], function($, moment) {
   // do your thing
   return something;
}