使用没有导出的UMD是否合理,只是增加一个依赖?

时间:2015-01-18 05:59:08

标签: javascript angularjs amd commonjs umd

我正在创建我的第一个用于开源分发的AngularJS模块。我想以一种易于他人消费的方式打包它。

UMD项目提供pattern用于导出与AMD,CommonJS(或至少Node)和浏览器全局变量兼容的JavaScript模块:

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(['b'], factory); // AMD
  } else if (typeof exports === 'object') {
    module.exports = factory(require('b')); // Node
  } else {
    root.returnExports = factory(root.b); // browser global (root is window)
  }
}(this, function (b) {
  // use b in some fashion
  return {}; // return a value to define the module export
}));

但是,由于AngularJS有自己的内部模块系统,因此只需调用angular对象上的方法即angular.module()即可注册模块。因此,UMD模块不需要输出任何东西;它只需要在angular上要求并采取行动。就前面的例子而言,我认为这看起来像这样:

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    factory(require(['b'])); // AMD
  } else if (typeof exports === 'object') {
    factory(require('b')); // Node
  } else {
    factory(root.b); // browser global (root is window)
  }
}(this, function (b) {
  // use b in some fashion
}));

或者,具体到我的情况:

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    factory(require(['angular'])); // AMD
  } else if (typeof exports === 'object') {
    factory(require('angular')); // Node
  } else {
    factory(root.angular); // browser global (root is window)
  }
}(this, function (angular) {
  angular.module( ... );
}));

这没什么大不了的,还是违背了UMD的精神?我问,因为我找不到任何不导出任何内容的UMD模式。

2 个答案:

答案 0 :(得分:1)

作为一个角度插件,它可能更好地提供一个导出构建器的模块,以便人们对“什么角度手段”负责。例如,假设我使用角度的自定义调试版本,但想要使用您的代码:现在,我不能,因为您已经决定要求角度为我。这似乎是一个好主意,但实际上并非如此:

var myangular = require('debug-angular/ext/symbolised');
var yourmodule = require('yourmodule');
yourmodule.register(myangular);

现在我知道,作为开发人员,您的代码将使用我的角度,而不是现在已经加载了两个不同版本的角度,其中包含了由此产生的所有热闹版本不匹配的错误。 / p>

所以一个更好的工厂就是这样:

(function (root, factory) {
  if (typeof define !== 'undefined' && define.amd) {
    define(['angular'] , function (angular) {
      factory(angular);
    });
  } else if (typeof module !== 'undefined' && module.exports) {
    module.exports = {
      register: function(angular) {
        factory(angular);
      }
    };
  } else {
    factory(root.angular); // browser global (root is window)
  }
}(this, function (angular) {
  angular.module( ... );
}));

答案 1 :(得分:1)

我没有看到使用这种模式有什么问题。正如您可能已经发现的那样,Angular并不像现有的模块系统那样使用它自己很好,但是模块不必输出任何东西。项目主模块多久输出一次?通常它只是依赖。

如果你正在寻找一个类似的例子,你可以看一下jQuery mousewheel插件,它使用UMD但依赖于jQuery。

  

摘录自jquery.mousewheel.js

(function (factory) {
    if ( typeof define === 'function' && define.amd ) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // Node/CommonJS style for Browserify
        module.exports = factory;
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function ($) {

一个区别是它返回Node / CommonJS导出的构造函数,以便您可以传入要扩展的jQuery对象。

另外,在AMD部分中,您的UMD实施存在一个问题。

你有:

factory(require(['b'])); // AMD

您需要的地方:

define(['b'], factory); // AMD

由于AMD是异步的,因此您无法同步需要角度模块。

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(['b'], factory); // AMD
  } else if (typeof exports === 'object') {
    factory(require('b')); // Node
  } else {
    factory(root.b); // browser global (root is window)
  }
}(this, function (b) {
  // use b in some fashion
}));