Мне нужно переструктурировать существующий модуль AMD, чтобы сделать его доступным для использования на страницах с/без RequjS. Как мне это сделать, и есть ли какой-нибудь примерный код? Предпочтительно, это был бы способ, не загрязняющий глобальное пространство имен, хотя и не строгое требование.
Как написать модуль AMD для использования на страницах без RequireJS?
Ответ 1
Это совсем не плохая идея, довольно часто JS libs необходимы для поддержки среды AMD/non AMD. Вот один из вариантов решения:
!function (name, definition) {
if (typeof module != 'undefined') module.exports = definition()
else if (typeof define == 'function' && define.amd) define(name, definition)
else this[name] = definition()
}('reqwest', function () {
// Module here
});
Единственным недостатком является то, что вы не можете запрашивать другие зависимости, поэтому это будет полезно только в автономных библиотеках, например, ниже
Ответ 2
Недавно я написал суть этой темы, поэтому я скопировал соответствующие биты ниже; однако, не стесняйтесь проверить оригинал Gist для получения дополнительной информации.
Следующий шаблонный планшет позволяет вам написать свой модуль один раз и работать в среде CJS/NodeJs, AMD или Browser Global.
Лучше всего использовать, когда...
- Вы переходите от кода имен (err, globals) к модулям AMD или CJS или к тем и другим.
- Вы еще не можете отфильтровать глобальные браузеры, но также необходимо протестировать свой код через NodeJS (например, Mocha)
Преимущества и компромиссы
- Формат одного модуля, позволяющий настроить таргетинг на AMD, CJS/NodeJS и старые глобальные браузерные браузеры, такие как
window.*
. - Позволяет определять несколько зависимостей.
- Выполнить тесты модулей с помощью CLI/NodeJS (например, Mocha).
- Меньше боли при постепенной миграции на модули CJS/NodeJS или AMD.
- Вы отказываетесь от Java-подобных пространств имен (например, com.company.package.module) - meh, они все равно беспорядочны.
- Этот (UMD) не является стандартом; чтобы быть справедливым, ни AMD (это соглашение с четко определенной спецификацией).
- Нетривиальное количество шаблона (и Ugly).
Пример
/**
* Creates a an "AppWidget" module that imports a "SingleDependency" constructor and exposes an "AppWidget" constructor.
*
* Allows you to access AppWidget as a CJS/AMD module (i.e. NodeJS or RequireJs):
*
* @example
* var AppWidget = require('app-widget')
*
* Allows you to access AppWidget as a legacy browser global:
*
* @example
* var AppWidget = window.AppWidget
*/
!(function (name, context, definition) {
if (typeof exports === 'object') { module.exports = definition(require); } else if (typeof define === 'function' && define.amd) { define(definition); } else { context[name] = definition(); }
}).call(this, 'AppWidget', this, function (require) {
'use strict'
// imports
var SingleDependency = (typeof require === 'function') ? require('./single-dependency') : window.SingleDependency;
var singleDependency = new SingleDependency();
function AppWidget() {}
AppWidget.prototype.start = function () {};
// exports
return AppWidget;
});
Ответ 3
Отъезд UMD. Вы должны найти образец, подходящий для ваших целей. Шаблоны несколько уродливы, но работают.
Ответ 4
Я думаю, что это довольно плохая идея.
Ваши возможные шаги, которые вы должны предпринять, чтобы убедиться, что он работает:
- убедитесь, что все зависимостей модулей загружены на эту страницу (jQuery, Backbone и другие)
- укажите ваш модуль (модули) на странице в том порядке, в котором вы знаете, что они должны быть выполнены
- убедитесь, что любой модуль, являющийся зависимостью другого модуля, создает глобальную переменную с тем же именем модуль "importing" ожидает и ссылается в своем коде
- убедитесь, что ваш модуль ссылается на зависимости (включая другие модули) с тем же именем
- переопределить/создать глобальный метод
define
, который выполняет функцию вашего модуля factory
И это только часть того, что вам нужно будет делать. Как насчет третьих сторон, которые должны быть совместимы с AMD для ваших страниц RequireJS (или, по крайней мере, быть в конфигурации shim
), но также должны быть глобальными для ваших страниц без необходимости?
Проще говоря, IMO, было бы проще переделать существующий код в версию AMD, чтобы сделать ваши модули не-AMD
Ответ 5
Основываясь на ответе Саймона Смита, я имел дело с зависимостями модулей:
(function (root, factory) {
if (typeof exports === "object") {
module.exports = factory();
} else if (typeof define === "function" && define.amd) {
define(['jquery', 'ol'], factory);
} else {
root.module_name = factory();
}
}(this, function (_$, _ol) {
return new function () {
// supposed that window.ol and window.$ are defined
var ol = goog.isDef(_ol) ? _ol : window.ol;
var $ = goog.isDef(_$) ? _$ : window.$;
}
}));
Где goog.isDef
есть функция Google Closure
:
goog.isDef = function(val) {
return val !== void 0;
};
Надеюсь, что это поможет кому-то.
Ответ 6
Отметьте Browserify, который создаст отдельный автономный .js файл со всеми зависимостями, встроенными в ваш код AMD/JS.
Затем вы можете отправить 2 версии кода, один для пользователей AMD, и один для пользователей "oldschool" js.