Разумно ли использовать UMD без экспорта, чтобы просто увеличить зависимость?

Я создаю свой первый модуль AngularJS, предназначенный для распространения с открытым исходным кодом. Я бы хотел упаковать его так, чтобы его могли легко использовать другие.

Проект UMD предоставляет шаблон для экспорта модулей JavaScript, совместимых с AMD, CommonJS (или хотя бы Node) и глобальными переменными браузера:

(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 ответа

Я не вижу ничего плохого в использовании этого шаблона. Как вы, вероятно, обнаружили, 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, который вы хотите расширить.


Кстати, есть одна проблема с вашей реализацией UMD, в разделе AMD.

У тебя есть:

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

Как угловой плагин, было бы лучше предложить модуль, который экспортирует компоновщик, чтобы люди отвечали за "что такое угловой". Например, скажем, я использую настроенную отладочную версию angular, но хочу использовать ваш код: сейчас я не могу, потому что вы решили потребовать angular in для меня. Это кажется отличной идеей, но на самом деле это не так:

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

Теперь я, как разработчик, знаю, что ваш код будет использовать мой angular, а не загружать две разные версии angular со всеми ошибками, возникающими из-за этого.

Таким образом, гораздо более приятная UMD фабрика была бы такой:

(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( ... );
}));
Другие вопросы по тегам