同时支持 CommonJS 和 AMD

IT技术 javascript amd commonjs
2021-03-02 18:08:40

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

  • 异步module定义
  • 通用JS
  • 将库的导出公开为全局命名空间对象(无加载器)
6个回答

是的,我把这个答案归功于ded和他很棒的module:

(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 + '!');
        }
    };
}));

然后可以使用它:

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

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

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

    <script src="mod.js"></script>
    <script>mod.sayHi('Marc');</script>
    

这种方法需要得到更多的宣传 - 如果 jQuery 和 co. 开始使用它的生活会容易得多!

这很棒。请注意,该测试typeof module != undefined正在测试 commonJS,但module可能会被其他可能包含的脚本(例如 QUnit)定义为全局对象,从而防止其在 AMD 下加载。所以我发现最好先切换顺序并测试 AMD。
2021-04-23 18:08:40
我必须define(name, [], definition);在第 3 行使用它才能与 Curl 一起使用。
2021-04-28 18:08:40
我将如何向“mod”module添加依赖项?
2021-04-28 18:08:40
如果module具有我想要的依赖项,这会起作用吗?如果在里面我做 var x = require ('./x'); 我希望在 amd 和 node 中正常工作,如果没有加载程序,我想使用 window.x
2021-05-10 18:08:40
这个想法是对的,在module定义周围使用包装器来欺骗module加载器。uRequire 使您不必为每个module编写这些包装器,这是相当痛苦的。它还有许多这样的包装器模板(UMD/UMDplain/AMD/nodejs)和其他好东西,比如'rootExports'noConflict()等等
2021-05-14 18:08:40

这是各种交叉兼容module格式的列表

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

UMD 是要走的路 - 检查uRequire.org,它从 AMD/CommonJS 转换为 UMD(还有 AMD/CommonJS/plain script)
2021-04-25 18:08:40

uRequire,通用module和资源转换器就是这样做的工具。

  • 它主要将AMD和CommonJS转换UMD/AMD/CommonJS/Plain script(不需要AMD加载器)

  • 它允许module的声明性导出,并带有noConflict()烘焙。

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

  • 它从 coffeescript、coco、Livescript、icedCoffeescript 转换而来,您可以在一个衬垫中添加自己的转换!

我无法使用此工具。在此处查看我的其他关于它的 stackoverflow 帖子
2021-05-06 18:08:40

只是为了更新一点关于@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 || {}));

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

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

有关真实示例,请参见:https : //gist.github.com/Nijikokun/5192472

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

  • 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 获得